Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #90734

Merged
merged 24 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7bde18a
implement type-changing-struct-update
SparrowLii Oct 19, 2021
f3679bc
move the processing part of `base_expr` into `check_expr_struct_fields`
SparrowLii Oct 29, 2021
1ab2616
Add feature trigger and correct `is_struct` check
SparrowLii Oct 29, 2021
926892d
Add feature trigger and enable is_struct check
SparrowLii Nov 5, 2021
02c1774
Give inline const separate DefKind
nbdd0121 Oct 2, 2021
468192a
Implement type inference for inline consts
nbdd0121 Oct 2, 2021
4acef9a
Add unit test for issue 78132
nbdd0121 Oct 3, 2021
1d32b20
Add unit test for issue 78174
nbdd0121 Oct 3, 2021
ff055e2
Ensure closure requirements are proven for inline const
nbdd0121 Oct 3, 2021
4060ed7
Add a FIXME note about what's missing
nbdd0121 Oct 3, 2021
d0f59f6
Fix closures within inline const
nbdd0121 Oct 23, 2021
c4103d4
Rename functions reflect that inline const is also "typeck_child"
nbdd0121 Nov 6, 2021
5bf3a5d
Make `compiler-docs` only control the default instead of being a hard…
jyn514 Nov 8, 2021
6192246
x.py: remove fixme by deleting code
jyn514 Nov 8, 2021
fefe1e9
Record more artifact sizes during self-profiling.
michaelwoerister Nov 8, 2021
db4e60b
document Box and box_free connection
asquared31415 Nov 9, 2021
10d65a9
Allow to run a specific rustdoc-js* test
GuillaumeGomez Nov 5, 2021
fd74c93
Rollup merge of #89561 - nbdd0121:const_typeck, r=nikomatsakis
matthiaskrgr Nov 9, 2021
610b4e5
Rollup merge of #90035 - SparrowLii:rfc2528, r=jackh726
matthiaskrgr Nov 9, 2021
730c6bf
Rollup merge of #90613 - GuillaumeGomez:specific-rustdoc-js-test, r=M…
matthiaskrgr Nov 9, 2021
2fff260
Rollup merge of #90683 - jyn514:compiler-docs, r=Mark-Simulacrum
matthiaskrgr Nov 9, 2021
21b0ce1
Rollup merge of #90685 - jyn514:remove-dead-code, r=Mark-Simulacrum
matthiaskrgr Nov 9, 2021
fd5a4f4
Rollup merge of #90701 - michaelwoerister:more-artifact-sizes, r=davi…
matthiaskrgr Nov 9, 2021
9c1aa12
Rollup merge of #90723 - asquared31415:box_docs, r=jyn514
matthiaskrgr Nov 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add feature trigger and enable is_struct check
  • Loading branch information
SparrowLii committed Nov 5, 2021
commit 926892ddc0b75b50f5d0a3483d829e501aa8e895
188 changes: 85 additions & 103 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
use rustc_infer::infer::InferOk;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::TypeError::FieldMisMatch;
use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts};
use rustc_middle::ty::relate::expected_found_bool;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::Ty;
use rustc_middle::ty::TypeFoldable;
Expand Down Expand Up @@ -1375,124 +1376,105 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

if let Some(base_expr) = base_expr {
let expected = if self.tcx.features().type_changing_struct_update {
NoExpectation
} else {
ExpectHasType(adt_ty)
};
let mut ty = self.check_expr_with_expectation(base_expr, expected);

let expected_ty = expected.to_option(&self).unwrap_or(adt_ty);
// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from ! to `expected`.
if ty.is_never() {
assert!(
!self.typeck_results.borrow().adjustments().contains_key(base_expr.hir_id),
"expression with never type wound up being adjusted"
);
let adj_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AdjustmentType,
span: base_expr.span,
});
self.apply_adjustments(
base_expr,
vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
);
ty = adj_ty;
}
let cause = self.misc(base_expr.span);
let mut fru_tys = None;
let mut err = None;
let is_struct;

if let ty::Adt(adt, substs) = expected_ty.kind() {
match ty.kind() {
ty::Adt(base_adt, base_subs) if adt == base_adt => {
if self.tcx.features().type_changing_struct_update {
let tys = variant
.fields
.iter()
.map(|f| {
let fru_ty = self.normalize_associated_types_in(
expr_span,
self.field_ty(base_expr.span, f, base_subs),
);
let ident = self.tcx.adjust_ident(f.ident, variant.def_id);
if let Some(_) = remaining_fields.remove(&ident) {
let target_ty = self.field_ty(base_expr.span, f, substs);
match self.at(&cause, self.param_env).sup(target_ty, fru_ty)
{
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations)
}
// FIXME: Need better diagnostics for `FieldMisMatch` error
Err(_) => {
if err.is_none() {
err = Some(self.report_mismatched_types(
// FIXME: We are currently creating two branches here in order to maintain
// consistency. But they should be merged as much as possible.
let fru_tys = if self.tcx.features().type_changing_struct_update {
let base_ty = self.check_expr(base_expr);
match adt_ty.kind() {
ty::Adt(adt, substs) if adt.is_struct() => {
match base_ty.kind() {
ty::Adt(base_adt, base_subs) if adt == base_adt => {
variant
.fields
.iter()
.map(|f| {
let fru_ty = self.normalize_associated_types_in(
expr_span,
self.field_ty(base_expr.span, f, base_subs),
);
let ident = self.tcx.adjust_ident(f.ident, variant.def_id);
if let Some(_) = remaining_fields.remove(&ident) {
let target_ty =
self.field_ty(base_expr.span, f, substs);
let cause = self.misc(base_expr.span);
match self
.at(&cause, self.param_env)
.sup(target_ty, fru_ty)
{
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations)
}
// FIXME: Need better diagnostics for `FieldMisMatch` error
Err(_) => self
.report_mismatched_types(
&cause,
target_ty,
fru_ty,
FieldMisMatch(
variant.ident.name,
ident.name,
),
))
}
)
.emit(),
}
}
}
fru_ty
})
.collect();
fru_tys = Some(tys);
} else {
err = self.demand_suptype_diag(base_expr.span, expected_ty, ty);
if err.is_some() && self.tcx.sess.is_nightly_build() {
feature_err(
&self.tcx.sess.parse_sess,
sym::type_changing_struct_update,
base_expr.span,
"type changing struct updating is experimental",
)
.emit();
fru_ty
})
.collect()
}
_ => {
return self
.report_mismatched_types(
&self.misc(base_expr.span),
adt_ty,
base_ty,
Sorts(expected_found_bool(true, adt_ty, base_ty)),
)
.emit();
}
}
}
_ => {
err = self.demand_suptype_diag(base_expr.span, expected_ty, ty);
return self
.tcx
.sess
.emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
}
}
is_struct = adt.is_struct();
if is_struct && fru_tys.is_none() {
fru_tys = Some(
variant
.fields
.iter()
.map(|f| {
self.normalize_associated_types_in(
expr_span,
f.ty(self.tcx, substs),
)
})
.collect(),
)
}
} else {
err = self.demand_suptype_diag(base_expr.span, expected_ty, ty);
is_struct = false;
}
if let Some(mut err) = err {
let expr = base_expr.peel_drop_temps();
self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None);
err.emit();
}
if let Some(fru_tys) = fru_tys {
self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys);
}
if !is_struct {
let e = FunctionalRecordUpdateOnNonStruct { span: base_expr.span };
self.tcx.sess.emit_err(e);
}
self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {
let base_ty = self.check_expr(base_expr);
let same_adt = match (adt_ty.kind(), base_ty.kind()) {
(ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true,
_ => false,
};
if self.tcx.sess.is_nightly_build() && same_adt {
feature_err(
&self.tcx.sess.parse_sess,
sym::type_changing_struct_update,
base_expr.span,
"type changing struct updating is experimental",
)
.emit();
}
});
match adt_ty.kind() {
ty::Adt(adt, substs) if adt.is_struct() => variant
.fields
.iter()
.map(|f| {
self.normalize_associated_types_in(expr_span, f.ty(self.tcx, substs))
})
.collect(),
_ => {
return self
.tcx
.sess
.emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
}
}
};
self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys);
} else if kind_name != "union" && !remaining_fields.is_empty() {
let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| {
!field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ fn fail_update() {
let m3 = Machine::<i32, i32> {
..m1
//~^ ERROR mismatched types [E0308]
//~| ERROR mismatched types [E0308]
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ LL | ..m1
= note: expected type `i32`
found type `f64`

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/type-generic-update.rs:51:11
|
LL | ..m1
| ^^ field type mismatch: Machine.message
|
= note: expected type `i32`
found type `f64`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.