From d227506683e846cbeb872e089d660187a7a6041f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sat, 17 Sep 2022 21:35:47 +0300 Subject: [PATCH] don't normalize in astconv We delay projection normalization to further stages in order to register user type annotations before normalization in HIR typeck. There are two consumers of astconv: ItemCtxt and FnCtxt. The former already expects unnormalized types from astconv, see its AstConv trait impl. The latter needs `RawTy` for a cleaner interface. Unfortunately astconv still needs the normalization machinery in order to resolve enum variants that have projections in the self type, e.g. `<::Assoc>::StructVariant {}`. This is why `AstConv::normalize_ty_2` is necessary. --- .../rustc_hir_analysis/src/astconv/mod.rs | 37 ++--- compiler/rustc_hir_analysis/src/collect.rs | 5 - compiler/rustc_hir_typeck/src/closure.rs | 6 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 67 +++++---- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 32 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 21 ++- .../rustc_hir_typeck/src/gather_locals.rs | 5 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 8 +- compiler/rustc_hir_typeck/src/pat.rs | 4 +- compiler/rustc_traits/src/type_op.rs | 1 + src/test/ui/const-generics/issue-97007.rs | 6 +- .../generic-associated-types/issue-91139.rs | 8 - .../issue-91139.stderr | 61 +------- .../normalize-under-binder/issue-85455.rs | 1 + .../normalize-under-binder/issue-85455.stderr | 13 +- ...malformed-projection-input-issue-102800.rs | 12 +- ...ormed-projection-input-issue-102800.stderr | 86 +---------- .../nll/user-annotations/ascribed-type-wf.rs | 5 +- .../user-annotations/ascribed-type-wf.stderr | 10 ++ .../user-annotations/dump-adt-brace-struct.rs | 2 + .../dump-adt-brace-struct.stderr | 18 ++- .../nll/user-annotations/normalization-2.rs | 80 ++++++++++ .../user-annotations/normalization-2.stderr | 141 ++++++++++++++++++ .../ui/ufcs/ufcs-partially-resolved.stderr | 2 +- 25 files changed, 376 insertions(+), 257 deletions(-) create mode 100644 src/test/ui/nll/user-annotations/ascribed-type-wf.stderr create mode 100644 src/test/ui/nll/user-annotations/normalization-2.rs create mode 100644 src/test/ui/nll/user-annotations/normalization-2.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1b334f65b9e..bcb695cc8e3 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -106,11 +106,9 @@ pub trait AstConv<'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; - /// Normalize an associated type coming from the user. - /// - /// This should only be used by astconv. Use `FnCtxt::normalize` - /// or `ObligationCtxt::normalize` in downstream crates. - fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; + fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + ty + } /// Invoked when we encounter an error from some prior pass /// (e.g., resolve) that is translated into a ty-error. This is @@ -485,14 +483,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Avoid ICE #86756 when type error recovery goes awry. return tcx.ty_error().into(); } - self.astconv - .normalize_ty( - self.span, - tcx.at(self.span) - .bound_type_of(param.def_id) - .subst(tcx, substs), - ) - .into() + tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into() } else if infer_args { self.astconv.ty_infer(Some(param), self.span).into() } else { @@ -1254,7 +1245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment<'_>, ) -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.normalize_ty(span, self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)) + self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs) } fn conv_object_ty_poly_trait_ref( @@ -1786,7 +1777,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ok(bound) } - // Create a type from a path to an associated type. + // Create a type from a path to an associated type or to an enum variant. // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for // the whole path. @@ -1814,7 +1805,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Check if we have an enum variant. let mut variant_resolution = None; - if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() { + if let ty::Adt(adt_def, adt_substs) = self.normalize_ty_2(span, qself_ty).kind() { if adt_def.is_enum() { let variant_def = adt_def .variants() @@ -1923,7 +1914,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { adt_substs, ); let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs); - let ty = self.normalize_ty(span, ty); return Ok((ty, DefKind::AssocTy, assoc_ty_did)); } } @@ -2020,7 +2010,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound); - let ty = self.normalize_ty(span, ty); if let Some(variant_def_id) = variant_resolution { tcx.struct_span_lint_hir( @@ -2156,7 +2145,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs)) + tcx.mk_projection(item_def_id, item_substs) } pub fn prohibit_generics<'a>( @@ -2417,7 +2406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note("`impl Trait` types can't have type parameters"); }); let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); - self.normalize_ty(span, tcx.mk_opaque(did, substs)) + tcx.mk_opaque(did, substs) } Res::Def( DefKind::Enum @@ -2577,7 +2566,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } tcx.ty_error_with_guaranteed(err.emit()) } else { - self.normalize_ty(span, ty) + ty } } Res::Def(DefKind::AssocTy, def_id) => { @@ -2720,8 +2709,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { None, ty::BoundConstness::NotConst, ); - EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) - .subst(tcx, substs) + EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs) } hir::TyKind::Array(ref ty, ref length) => { let length = match length { @@ -2731,8 +2719,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); - self.normalize_ty(ast_ty.span, array_ty) + tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)) } hir::TyKind::Typeof(ref e) => { let ty_erased = tcx.type_of(e.def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 7afde550b42..fd54aec480a 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -505,11 +505,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } } - fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - // Types in item signatures are not normalized to avoid undue dependencies. - ty - } - fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { // There's no obvious place to track this, so just let it go. } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 3453da500b9..399702fd41a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -647,14 +647,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), bound_vars, ); - // Astconv can't normalize inputs or outputs with escaping bound vars, - // so normalize them here, after we've wrapped them in a binder. - let result = self.normalize(self.tcx.hir().span(hir_id), result); let c_result = self.inh.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); - result + // Normalize only after registering in `user_provided_sigs`. + self.normalize(self.tcx.hir().span(hir_id), result) } /// Invoked when we are translating the generator that results diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 634688de01a..3e05f67b74b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1,7 +1,7 @@ use crate::callee::{self, DeferredCallResolution}; use crate::method::{self, MethodCallee, SelfSource}; use crate::rvalue_scopes; -use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; +use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; @@ -410,23 +410,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn create_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> { + RawTy { raw: ty, normalized: self.normalize(span, ty) } + } + + pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> { let t = >::ast_ty_to_ty(self, ast_t); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); - t + self.create_raw_ty(ast_t.span, t) } pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); - if Self::can_contain_user_lifetime_bounds(ty) { - let c_ty = self.canonicalize_response(UserType::Ty(ty)); + if Self::can_contain_user_lifetime_bounds(ty.raw) { + let c_ty = self.canonicalize_response(UserType::Ty(ty.raw)); debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty); self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); } - ty + ty.normalized } pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> { @@ -780,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, - ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { + ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!( "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span @@ -803,7 +807,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - (>::ast_ty_to_ty_in_path(self, qself), qself, segment) + let ty = >::ast_ty_to_ty_in_path(self, qself); + (self.create_raw_ty(span, ty), qself, segment) } QPath::LangItem(..) => { bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") @@ -811,7 +816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) { - self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); + self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None)); // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)); @@ -819,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let item_name = item_segment.ident; let result = self - .resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id) + .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id) .or_else(|error| { let result = match error { method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), @@ -830,13 +835,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise, // register a WF obligation so that we can detect any additional // errors in the self type. - if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) { - self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); + if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) { + self.register_wf_obligation( + ty.raw.into(), + qself.span, + traits::WellFormed(None), + ); } if item_name.name != kw::Empty { if let Some(mut e) = self.report_method_error( span, - ty, + ty.normalized, item_name, SelfSource::QPath(qself), error, @@ -849,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if result.is_ok() { - self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); + self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None)); } // Write back the new resolution. @@ -986,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn instantiate_value_path( &self, segments: &[hir::PathSegment<'_>], - self_ty: Option>, + self_ty: Option>, res: Res, span: Span, hir_id: hir::HirId, @@ -996,7 +1005,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let path_segs = match res { Res::Local(_) | Res::SelfCtor(_) => vec![], Res::Def(kind, def_id) => >::def_ids_for_value_path_segments( - self, segments, self_ty, kind, def_id, + self, + segments, + self_ty.map(|ty| ty.normalized), + kind, + def_id, ), _ => bug!("instantiate_value_path on {:?}", res), }; @@ -1007,8 +1020,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => { - let adt_def = self_ty.ty_adt_def().unwrap(); - user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty }); + let adt_def = self_ty.normalized.ty_adt_def().unwrap(); + user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw }); is_alias_variant_ctor = true; } Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => { @@ -1027,7 +1040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inherent impl, we need to record the // `T` for posterity (see `UserSelfTy` for // details). - let self_ty = self_ty.expect("UFCS sugared assoc missing Self"); + let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw; user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty }); } } @@ -1109,7 +1122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or(false); let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res { - let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id)); + let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id)); match *ty.kind() { ty::Adt(adt_def, substs) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); @@ -1193,7 +1206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { >::ast_region_to_region(self.fcx, lt, Some(param)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.fcx.to_ty(ty).into() + self.fcx.to_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.fcx.const_arg_to_const(&ct.value, param.def_id).into() @@ -1227,7 +1240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is missing. let default = tcx.bound_type_of(param.def_id); self.fcx - .normalize_ty(self.span, default.subst(tcx, substs.unwrap())) + .normalize_ty_2(self.span, default.subst(tcx, substs.unwrap())) .into() } else { // If no type arguments were provided, we have to infer them. @@ -1250,13 +1263,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let substs = self_ctor_substs.unwrap_or_else(|| { + let substs_raw = self_ctor_substs.unwrap_or_else(|| { >::create_substs_for_generic_args( tcx, def_id, &[], has_self, - self_ty, + self_ty.map(|s| s.raw), &arg_count, &mut CreateCtorSubstsContext { fcx: self, @@ -1269,7 +1282,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); // First, store the "user substs" for later. - self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty); + self.write_user_type_annotation_from_substs(hir_id, def_id, substs_raw, user_self_ty); + + // Normalize only after registering type annotations. + let substs = self.normalize(span, substs_raw); self.add_required_obligations_for_hir(span, def_id, &substs, hir_id); @@ -1287,6 +1303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // with the substituted impl type. // This also occurs for an enum variant on a type alias. let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs)); + let self_ty = self.normalize(span, self_ty); match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7d6b4aaebf4..6a822568775 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -5,7 +5,7 @@ use crate::method::MethodCallee; use crate::Expectation::*; use crate::TupleArgumentsFlag::*; use crate::{ - struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, + struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy, TupleArgumentsFlag, }; use rustc_ast as ast; @@ -1231,13 +1231,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return None; } - Res::Def(DefKind::Variant, _) => match ty.kind() { + Res::Def(DefKind::Variant, _) => match ty.normalized.kind() { ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)), - _ => bug!("unexpected type: {:?}", ty), + _ => bug!("unexpected type: {:?}", ty.normalized), }, Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfTyParam { .. } - | Res::SelfTyAlias { .. } => match ty.kind() { + | Res::SelfTyAlias { .. } => match ty.normalized.kind() { ty::Adt(adt, substs) if !adt.is_enum() => { Some((adt.non_enum_variant(), adt.did(), substs)) } @@ -1248,14 +1248,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some((variant, did, substs)) = variant { debug!("check_struct_path: did={:?} substs={:?}", did, substs); - self.write_user_type_annotation_from_substs(hir_id, did, substs, None); + + // FIXME(aliemjay): We're using UserSelfTy unconditionally here because it is the only + // way to register the raw user ty, because `substs` is normalized. + let self_ty = ty::UserSelfTy { impl_def_id: did, self_ty: ty.raw }; + self.write_user_type_annotation_from_substs(hir_id, did, substs, Some(self_ty)); // Check bounds on type arguments used in the path. self.add_required_obligations_for_hir(path_span, did, substs, hir_id); - Some((variant, ty)) + Some((variant, ty.normalized)) } else { - match ty.kind() { + match ty.normalized.kind() { ty::Error(_) => { // E0071 might be caused by a spelling error, which will have // already caused an error message and probably a suggestion @@ -1268,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { path_span, E0071, "expected struct, variant or union type, found {}", - ty.sort_string(self.tcx) + ty.normalized.sort_string(self.tcx) ) .span_label(path_span, "not a struct") .emit(); @@ -1656,20 +1660,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &QPath<'_>, path_span: Span, hir_id: hir::HirId, - ) -> (Res, Ty<'tcx>) { + ) -> (Res, RawTy<'tcx>) { match *qpath { QPath::Resolved(ref maybe_qself, ref path) => { - let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); + let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); let ty = >::res_to_ty(self, self_ty, path, true); - (path.res, ty) + (path.res, self.create_raw_ty(path_span, ty)) } QPath::TypeRelative(ref qself, ref segment) => { let ty = self.to_ty(qself); let result = >::associated_path_to_ty( - self, hir_id, path_span, ty, qself, segment, true, + self, hir_id, path_span, ty.raw, qself, segment, true, ); let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error()); + let ty = self.create_raw_ty(path_span, ty); let result = result.map(|(_, kind, def_id)| (kind, def_id)); // Write back the new resolution. @@ -1678,7 +1683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } QPath::LangItem(lang_item, span, id) => { - self.resolve_lang_item_path(lang_item, span, hir_id, id) + let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id); + (res, self.create_raw_ty(path_span, ty)) } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 30b59da7852..d7e53a0aa04 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -17,8 +17,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, Const, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::{self, Span}; @@ -298,7 +297,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { self.tcx().mk_projection(item_def_id, item_substs) } - fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + fn normalize_ty_2(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { if ty.has_escaping_bound_vars() { ty // FIXME: normalization and escaping regions } else { @@ -310,7 +309,19 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { self.infcx.set_tainted_by_errors(e) } - fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) { - self.write_ty(hir_id, ty) + fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) { + self.write_ty(hir_id, self.normalize_ty_2(span, ty)) } } + +/// Represents a user-provided type in the raw form (never normalized). +/// +/// This is a bridge between the interface of `AstConv`, which outputs a raw `Ty`, +/// and the API in this module, which expect `Ty` to be fully normalized. +#[derive(Clone, Copy, Debug)] +pub struct RawTy<'tcx> { + pub raw: Ty<'tcx>, + + /// The normalized form of `raw`, stored here for efficiency. + pub normalized: Ty<'tcx>, +} diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 9a096f24fac..15dd3412c34 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -77,7 +77,8 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.to_ty(&ty); - let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty)); + let c_ty = + self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results @@ -85,7 +86,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { .user_provided_types_mut() .insert(ty.hir_id, c_ty); - Some(LocalTy { decl_ty: o_ty, revealed_ty: o_ty }) + Some(LocalTy { decl_ty: o_ty.normalized, revealed_ty: o_ty.normalized }) } None => None, }; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 99e09b86a23..69929589541 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -297,7 +297,7 @@ fn typeck_with_fallback<'tcx>( fcx.resolve_generator_interiors(def_id.to_def_id()); for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { - let ty = fcx.normalize_ty(span, ty); + let ty = fcx.normalize(span, ty); fcx.require_type_is_sized(ty, span, code); } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 218c54688aa..f2a41720b60 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -372,7 +372,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { .into() } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.cfcx.to_ty(ty).into() + self.cfcx.to_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() @@ -397,7 +397,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.cfcx.var_for_def(self.cfcx.span, param) } } - >::create_substs_for_generic_args( + let substs = >::create_substs_for_generic_args( self.tcx, pick.item.def_id, parent_substs, @@ -405,7 +405,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { None, &arg_count_correct, &mut MethodSubstsCtxt { cfcx: self, pick, seg }, - ) + ); + // FIXME(aliemjay): Type annotation should be registered before normalization. + self.normalize(self.span, substs) } fn unify_receivers( diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e0304fa2d3b..1075378a159 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1,4 +1,4 @@ -use crate::FnCtxt; +use crate::{FnCtxt, RawTy}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ @@ -842,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &Pat<'tcx>, qpath: &hir::QPath<'_>, - path_resolution: (Res, Option>, &'tcx [hir::PathSegment<'tcx>]), + path_resolution: (Res, Option>, &'tcx [hir::PathSegment<'tcx>]), expected: Ty<'tcx>, ti: TopInfo<'tcx>, ) -> Ty<'tcx> { diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 7f964afde80..f6eca977430 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -91,6 +91,7 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>( } if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { + let self_ty = ocx.normalize(&cause, param_env, self_ty); let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs); let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); diff --git a/src/test/ui/const-generics/issue-97007.rs b/src/test/ui/const-generics/issue-97007.rs index 7036834c4b1..7b9b9701ff1 100644 --- a/src/test/ui/const-generics/issue-97007.rs +++ b/src/test/ui/const-generics/issue-97007.rs @@ -1,4 +1,8 @@ -// check-pass +//~ ERROR broken MIR + +// known-bug +// failure-status: 101 +// rustc-env: RUSTC_BACKTRACE=0 #![feature(adt_const_params, generic_const_exprs)] #![allow(incomplete_features)] diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index e321da53d56..adc0cb4e042 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -14,14 +14,6 @@ fn foo() { let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); //~^ ERROR `T` does not live long enough //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` does not live long enough - //~| ERROR `T` may not live long enough - //~| ERROR `T` may not live long enough // // FIXME: This error is bogus, but it arises because we try to validate // that `<() as Foo>::Type<'a>` is valid, which requires proving diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr index 5485570cecd..d9d76adfbb5 100644 --- a/src/test/ui/generic-associated-types/issue-91139.stderr +++ b/src/test/ui/generic-associated-types/issue-91139.stderr @@ -10,64 +10,5 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:12 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:12 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... - | -LL | fn foo() { - | +++++++++ - -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^ - -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^ - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... - | -LL | fn foo() { - | +++++++++ - -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^ - -error: `T` does not live long enough - --> $DIR/issue-91139.rs:14:58 - | -LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); - | ^^^^^^^^^ - -error: aborting due to 10 previous errors - -For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs index c10a0888a4f..8aa29926d4f 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -7,6 +7,7 @@ trait SomeTrait<'a> { fn give_me_ice() { callee:: >::Associated>(); //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] + //~| ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] } fn callee>() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr index 25a4f6088de..3240518fbbe 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -1,3 +1,14 @@ +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied + --> $DIR/issue-85455.rs:8:14 + | +LL | callee:: >::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice SomeTrait<'a>>() { + | +++++++++++++++++++++++ + error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied --> $DIR/issue-85455.rs:8:5 | @@ -9,6 +20,6 @@ help: consider restricting type parameter `T` LL | fn give_me_ice SomeTrait<'a>>() { | +++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs index 25f47f5b6f6..260c16c17d4 100644 --- a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs +++ b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs @@ -16,16 +16,6 @@ impl Trait for &'static () { fn main() { let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - //~^ ERROR lifetime may not live long enough - //~| ERROR higher-ranked subtype error - //~| ERROR higher-ranked subtype error - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough - //~| ERROR implementation of `Trait` is not general enough + //~^ ERROR implementation of `Trait` is not general enough //~| ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr index dbd5dabd1da..46dba006433 100644 --- a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr +++ b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr @@ -1,33 +1,3 @@ -error: lifetime may not live long enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^-^ - | || - | |has type `<&'1 () as Trait>::Ty` - | requires that `'1` must outlive `'static` - -error: higher-ranked subtype error - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^ - -error: higher-ranked subtype error - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^ - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - error: implementation of `Trait` is not general enough --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 | @@ -46,59 +16,5 @@ LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... = note: ...but `Trait` is actually implemented for the type `&'static ()` -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: implementation of `Trait` is not general enough - --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48 - | -LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; - | ^^^^^^ implementation of `Trait` is not general enough - | - = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `&'static ()` - -error: aborting due to 12 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/user-annotations/ascribed-type-wf.rs b/src/test/ui/nll/user-annotations/ascribed-type-wf.rs index 14460dea5b5..5db02c46ec3 100644 --- a/src/test/ui/nll/user-annotations/ascribed-type-wf.rs +++ b/src/test/ui/nll/user-annotations/ascribed-type-wf.rs @@ -1,5 +1,5 @@ -// check-pass -// known-bug: #101350 +// Regression test for #101350. +// check-fail trait Trait { type Ty; @@ -11,6 +11,7 @@ impl Trait for &'static () { fn extend<'a>() { None::<<&'a () as Trait>::Ty>; + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/src/test/ui/nll/user-annotations/ascribed-type-wf.stderr b/src/test/ui/nll/user-annotations/ascribed-type-wf.stderr new file mode 100644 index 00000000000..91e7c6b8ecf --- /dev/null +++ b/src/test/ui/nll/user-annotations/ascribed-type-wf.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/ascribed-type-wf.rs:13:5 + | +LL | fn extend<'a>() { + | -- lifetime `'a` defined here +LL | None::<<&'a () as Trait>::Ty>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs index ccda9129dab..8a80958fc67 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs @@ -11,8 +11,10 @@ struct SomeStruct { t: T } #[rustc_dump_user_substs] fn main() { SomeStruct { t: 22 }; // Nothing given, no annotation. + //~^ ERROR SomeStruct<^0> SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. + //~^ ERROR SomeStruct<^0> SomeStruct:: { t: 22 }; // No lifetime bounds given. diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr index 5860621909c..b5adc584b28 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -1,8 +1,20 @@ -error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None } - --> $DIR/dump-adt-brace-struct.rs:19:5 +error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) } + --> $DIR/dump-adt-brace-struct.rs:13:5 + | +LL | SomeStruct { t: 22 }; // Nothing given, no annotation. + | ^^^^^^^^^^^^^^^^^^^^ + +error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) } + --> $DIR/dump-adt-brace-struct.rs:16:5 + | +LL | SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<&ReStatic u32> }) } + --> $DIR/dump-adt-brace-struct.rs:21:5 | LL | SomeStruct::<&'static u32> { t: &22 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/user-annotations/normalization-2.rs b/src/test/ui/nll/user-annotations/normalization-2.rs new file mode 100644 index 00000000000..00e9eb651cd --- /dev/null +++ b/src/test/ui/nll/user-annotations/normalization-2.rs @@ -0,0 +1,80 @@ +// Make sure we honor region constraints when normalizing type annotations. + +// check-fail + +#![feature(more_qualified_paths)] + +trait Trait { + type Assoc; +} + +impl Trait for T +where + T: 'static, +{ + type Assoc = MyTy<()>; +} + +enum MyTy { + Unit, + Tuple(), + Struct {}, + Dumb(T), +} + +impl MyTy { + fn method() {} +} + +type Ty<'a> = <&'a () as Trait>::Assoc; + +fn test_local<'a>() { + let _: Ty<'a> = MyTy::Unit; + //~^ ERROR lifetime may not live long enough +} + +fn test_closure_sig<'a, 'b>() { + |_: Ty<'a>| {}; + //~^ ERROR lifetime may not live long enough + || -> Option> { None }; + //~^ ERROR lifetime may not live long enough +} + +fn test_path<'a, 'b, 'c, 'd>() { + >::method::>; + //~^ ERROR lifetime may not live long enough + >::method::>; + //~^ ERROR lifetime may not live long enough +} + +fn test_call<'a, 'b, 'c>() { + >::method::>(); + //~^ ERROR lifetime may not live long enough + >::method::>(); + //~^ ERROR lifetime may not live long enough +} + +fn test_variants<'a, 'b, 'c>() { + >::Struct {}; //TODO + //~^ ERROR lifetime may not live long enough + >::Tuple(); + //~^ ERROR lifetime may not live long enough + >::Unit; + //~^ ERROR lifetime may not live long enough +} + +fn test_pattern<'a, 'b, 'c>() { + use MyTy::*; + match MyTy::Unit { + Struct::> {..} => {}, + //~^ ERROR lifetime may not live long enough + Tuple::> (..) => {}, + //~^ ERROR lifetime may not live long enough + Unit::> => {}, + //~^ ERROR lifetime may not live long enough + Dumb(_) => {}, + }; +} + + +fn main() {} diff --git a/src/test/ui/nll/user-annotations/normalization-2.stderr b/src/test/ui/nll/user-annotations/normalization-2.stderr new file mode 100644 index 00000000000..3c235171ef5 --- /dev/null +++ b/src/test/ui/nll/user-annotations/normalization-2.stderr @@ -0,0 +1,141 @@ +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:32:12 + | +LL | fn test_local<'a>() { + | -- lifetime `'a` defined here +LL | let _: Ty<'a> = MyTy::Unit; + | ^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:37:6 + | +LL | fn test_closure_sig<'a, 'b>() { + | -- lifetime `'a` defined here +LL | |_: Ty<'a>| {}; + | ^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:39:11 + | +LL | fn test_closure_sig<'a, 'b>() { + | -- lifetime `'b` defined here +... +LL | || -> Option> { None }; + | ^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:44:5 + | +LL | fn test_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'a` defined here +LL | >::method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:46:5 + | +LL | fn test_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'b` defined here +... +LL | >::method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:51:5 + | +LL | fn test_call<'a, 'b, 'c>() { + | -- lifetime `'a` defined here +LL | >::method::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:53:5 + | +LL | fn test_call<'a, 'b, 'c>() { + | -- lifetime `'b` defined here +... +LL | >::method::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:58:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'a` defined here +LL | >::Struct {}; //TODO + | ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:60:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'b` defined here +... +LL | >::Tuple(); + | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:62:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'c` defined here +... +LL | >::Unit; + | ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:69:9 + | +LL | fn test_pattern<'a, 'b, 'c>() { + | -- lifetime `'a` defined here +... +LL | Struct::> {..} => {}, + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:71:9 + | +LL | fn test_pattern<'a, 'b, 'c>() { + | -- lifetime `'b` defined here +... +LL | Tuple::> (..) => {}, + | ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:73:9 + | +LL | fn test_pattern<'a, 'b, 'c>() { + | -- lifetime `'c` defined here +... +LL | Unit::> => {}, + | ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + +error: aborting due to 13 previous errors + diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 3950dc9877c..5f7f6aa9f6e 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -205,7 +205,7 @@ error[E0223]: ambiguous associated type --> $DIR/ufcs-partially-resolved.rs:36:12 | LL | let _: ::Y::NN; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::NN` + | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::Y as Trait>::NN` error[E0599]: no associated item named `NN` found for type `u16` in the current scope --> $DIR/ufcs-partially-resolved.rs:38:20