diff options
Diffstat (limited to 'compiler')
18 files changed, 98 insertions, 41 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3a55396248e..3d8eee6f597 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -497,7 +497,6 @@ pub struct WhereRegionPredicate { /// E.g., `T = int`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct WhereEqPredicate { - pub id: NodeId, pub span: Span, pub lhs_ty: P<Ty>, pub rhs_ty: P<Ty>, @@ -3042,6 +3041,7 @@ mod size_asserts { static_assert_size!(Attribute, 32); static_assert_size!(Block, 48); static_assert_size!(Expr, 104); + static_assert_size!(ExprKind, 72); static_assert_size!(Fn, 192); static_assert_size!(ForeignItem, 160); static_assert_size!(ForeignItemKind, 72); @@ -3051,9 +3051,13 @@ mod size_asserts { static_assert_size!(Item, 200); static_assert_size!(ItemKind, 112); static_assert_size!(Lit, 48); + static_assert_size!(LitKind, 24); static_assert_size!(Pat, 120); + static_assert_size!(PatKind, 96); static_assert_size!(Path, 40); static_assert_size!(PathSegment, 24); static_assert_size!(Stmt, 32); + static_assert_size!(StmtKind, 16); static_assert_size!(Ty, 96); + static_assert_size!(TyKind, 72); } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 54e2f7557e5..0520319e3be 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -935,8 +935,7 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); } WherePredicate::EqPredicate(ep) => { - let WhereEqPredicate { id, span, lhs_ty, rhs_ty } = ep; - vis.visit_id(id); + let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep; vis.visit_span(span); vis.visit_ty(lhs_ty); vis.visit_ty(rhs_ty); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ee4c0036f76..0f1bab24f96 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1498,9 +1498,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ), in_where_clause: true, }), - WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => { + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - hir_id: self.lower_node_id(id), lhs_ty: self .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), rhs_ty: self diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index ef64f52d40b..9f3a80ea7cb 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -640,11 +640,7 @@ impl<'a> TraitDef<'a> { } ast::WherePredicate::EqPredicate(we) => { let span = we.span.with_ctxt(ctxt); - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - id: ast::DUMMY_NODE_ID, - span, - ..we.clone() - }) + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { span, ..we.clone() }) } } })); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 584e86d51d9..ca1705f26b5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -778,7 +778,6 @@ impl<'hir> WhereRegionPredicate<'hir> { /// An equality predicate (e.g., `T = int`); currently unsupported. #[derive(Debug, HashStable_Generic)] pub struct WhereEqPredicate<'hir> { - pub hir_id: HirId, pub span: Span, pub lhs_ty: &'hir Ty<'hir>, pub rhs_ty: &'hir Ty<'hir>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 900370937f7..3d5e22add71 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -876,10 +876,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( visitor.visit_lifetime(lifetime); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicate::EqPredicate(WhereEqPredicate { - hir_id, ref lhs_ty, ref rhs_ty, .. - }) => { - visitor.visit_id(hir_id); + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index fcb87a9f32f..3c7dac2bfd8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1750,6 +1750,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values && let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() && let Some(def_id) = def_id.as_local() + && terr.involves_regions() { let span = self.tcx.def_span(def_id); diag.span_note(span, "this closure does not fulfill the lifetime requirements"); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1e26e7bb86e..444817f396e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1935,6 +1935,18 @@ impl<'tcx> TypeTrace<'tcx> { } } + pub fn poly_trait_refs( + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: ty::PolyTraitRef<'tcx>, + b: ty::PolyTraitRef<'tcx>, + ) -> TypeTrace<'tcx> { + TypeTrace { + cause: cause.clone(), + values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a.into(), b.into())), + } + } + pub fn consts( cause: &ObligationCause<'tcx>, a_is_expected: bool, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 8e6af936ded..ac89bec702e 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -74,6 +74,18 @@ pub enum TypeError<'tcx> { TargetFeatureCast(DefId), } +impl TypeError<'_> { + pub fn involves_regions(self) -> bool { + match self { + TypeError::RegionsDoesNotOutlive(_, _) + | TypeError::RegionsInsufficientlyPolymorphic(_, _) + | TypeError::RegionsOverlyPolymorphic(_, _) + | TypeError::RegionsPlaceholderMismatch => true, + _ => false, + } + } +} + /// Explains the source of a type err in a short, human readable way. This is meant to be placed /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()` /// afterwards to present additional details, particularly when it comes to lifetime-related diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 1acfd93d86f..5e5f2fd7d9f 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -314,7 +314,6 @@ impl<'a> Parser<'a> { span: lo.to(self.prev_token.span), lhs_ty: ty, rhs_ty, - id: ast::DUMMY_NODE_ID, })) } else { self.maybe_recover_bounds_doubled_colon(&ty)?; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 8332c171a9c..fc7fb866f11 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -527,7 +527,7 @@ impl<'a> Parser<'a> { Ok(ident_gen_args) => ident_gen_args, Err(()) => return Ok(Some(AngleBracketedArg::Arg(arg))), }; - if binder.is_some() { + if binder { // FIXME(compiler-errors): this could be improved by suggesting lifting // this up to the trait, at least before this becomes real syntax. // e.g. `Trait<for<'a> Assoc = Ty>` -> `for<'a> Trait<Assoc = Ty>` @@ -720,28 +720,24 @@ impl<'a> Parser<'a> { /// Given a arg inside of generics, we try to destructure it as if it were the LHS in /// `LHS = ...`, i.e. an associated type binding. - /// This returns (optionally, if they are present) any `for<'a, 'b>` binder args, the + /// This returns a bool indicating if there are any `for<'a, 'b>` binder args, the /// identifier, and any GAT arguments. fn get_ident_from_generic_arg( &self, gen_arg: &GenericArg, - ) -> Result<(Option<Vec<ast::GenericParam>>, Ident, Option<GenericArgs>), ()> { + ) -> Result<(bool, Ident, Option<GenericArgs>), ()> { if let GenericArg::Type(ty) = gen_arg { if let ast::TyKind::Path(qself, path) = &ty.kind && qself.is_none() && let [seg] = path.segments.as_slice() { - return Ok((None, seg.ident, seg.args.as_deref().cloned())); + return Ok((false, seg.ident, seg.args.as_deref().cloned())); } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)] = bounds.as_slice() && let [seg] = trait_ref.trait_ref.path.segments.as_slice() { - return Ok(( - Some(trait_ref.bound_generic_params.clone()), - seg.ident, - seg.args.as_deref().cloned(), - )); + return Ok((true, seg.ident, seg.args.as_deref().cloned())); } } Err(()) diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs index 59c6a95c2c5..98d3e79c8e9 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_gnullvm_base::opts(); - base.max_atomic_width = Some(64); + base.max_atomic_width = Some(128); base.features = "+neon,+fp-armv8".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs index 856ec4fb0b4..7c4544b3f33 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); - base.max_atomic_width = Some(64); + base.max_atomic_width = Some(128); base.features = "+neon,+fp-armv8".into(); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs index 162b091b269..3ef04c67668 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs @@ -7,7 +7,7 @@ use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = uefi_msvc_base::opts(); - base.max_atomic_width = Some(64); + base.max_atomic_width = Some(128); base.add_pre_link_args(LinkerFlavor::Msvc, &["/machine:arm64"]); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs index 54247fd93f2..db4dbf817b8 100644 --- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs @@ -2,7 +2,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); - base.max_atomic_width = Some(64); + base.max_atomic_width = Some(128); Target { llvm_target: "aarch64-pc-windows-msvc".into(), diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index 7b23fe1c482..cb7f5f2a583 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { arch: "aarch64".into(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), - max_atomic_width: Some(64), + max_atomic_width: Some(128), forces_embed_bitcode: true, // These arguments are not actually invoked - they just have // to look right to pass App Store validation. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4260cb53adc..1a39a168038 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -22,6 +22,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::GenericParam; use rustc_hir::Item; use rustc_hir::Node; +use rustc_infer::infer::TypeTrace; use rustc_infer::traits::TraitEngine; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -941,9 +942,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + let mut not_tupled = false; + let found = match found_trait_ref.skip_binder().substs.type_at(1).kind() { ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], - _ => vec![ArgKind::empty()], + _ => { + not_tupled = true; + vec![ArgKind::empty()] + } }; let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); @@ -951,10 +957,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::Tuple(ref tys) => { tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect() } - _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], + _ => { + not_tupled = true; + vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())] + } }; - if found.len() == expected.len() { + // If this is a `Fn` family trait and either the expected or found + // is not tupled, then fall back to just a regular mismatch error. + // This shouldn't be common unless manually implementing one of the + // traits manually, but don't make it more confusing when it does + // happen. + if Some(expected_trait_ref.def_id()) != tcx.lang_items().gen_trait() && not_tupled { + self.report_and_explain_type_error( + TypeTrace::poly_trait_refs( + &obligation.cause, + true, + expected_trait_ref, + found_trait_ref, + ), + ty::error::TypeError::Mismatch, + ) + } else if found.len() == expected.len() { self.report_closure_arg_mismatch( span, found_span, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 9c2fdd87516..c82c819169d 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2193,7 +2193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0610, "`{expr_t}` is a primitive type and therefore doesn't have fields", ); - let is_valid_suffix = |field: String| { + let is_valid_suffix = |field: &str| { if field == "f32" || field == "f64" { return true; } @@ -2218,20 +2218,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let suffix = chars.collect::<String>(); suffix.is_empty() || suffix == "f32" || suffix == "f64" }; + let maybe_partial_suffix = |field: &str| -> Option<&str> { + let first_chars = ['f', 'l']; + if field.len() >= 1 + && field.to_lowercase().starts_with(first_chars) + && field[1..].chars().all(|c| c.is_ascii_digit()) + { + if field.to_lowercase().starts_with(['f']) { Some("f32") } else { Some("f64") } + } else { + None + } + }; if let ty::Infer(ty::IntVar(_)) = expr_t.kind() && let ExprKind::Lit(Spanned { node: ast::LitKind::Int(_, ast::LitIntType::Unsuffixed), .. }) = base.kind && !base.span.from_expansion() - && is_valid_suffix(field_name) { - err.span_suggestion_verbose( - field.span.shrink_to_lo(), - "If the number is meant to be a floating point number, consider adding a `0` after the period", - '0', - Applicability::MaybeIncorrect, - ); + if is_valid_suffix(&field_name) { + err.span_suggestion_verbose( + field.span.shrink_to_lo(), + "if intended to be a floating point literal, consider adding a `0` after the period", + '0', + Applicability::MaybeIncorrect, + ); + } else if let Some(correct_suffix) = maybe_partial_suffix(&field_name) { + err.span_suggestion_verbose( + field.span, + format!("if intended to be a floating point literal, consider adding a `0` after the period and a `{correct_suffix}` suffix"), + format!("0{correct_suffix}"), + Applicability::MaybeIncorrect, + ); + } } err.emit(); } |
