Auto merge of #101947 - aliemjay:astconv-normalize, r=lcnr
Don't normalize in AstConv See individual commits. Fixes #101350 Fixes #54940
This commit is contained in:
commit
af58fc8699
@ -1,13 +1,13 @@
|
||||
use std::fmt;
|
||||
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::infer::{canonical::Canonical, InferOk};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
|
||||
use rustc_trait_selection::traits::query::Fallible;
|
||||
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
||||
|
||||
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
|
||||
|
||||
@ -177,4 +177,74 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
value
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn ascribe_user_type(
|
||||
&mut self,
|
||||
mir_ty: Ty<'tcx>,
|
||||
user_ty: ty::UserType<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
// FIXME: Ideally MIR types are normalized, but this is not always true.
|
||||
let mir_ty = self.normalize(mir_ty, Locations::All(span));
|
||||
|
||||
self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::Boring,
|
||||
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
span_mirbug!(
|
||||
self,
|
||||
span,
|
||||
"ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
|
||||
///
|
||||
/// FIXME(#104478, #104477): This is a hack for backward-compatibility.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn ascribe_user_type_skip_wf(
|
||||
&mut self,
|
||||
mir_ty: Ty<'tcx>,
|
||||
user_ty: ty::UserType<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
let ty::UserType::Ty(user_ty) = user_ty else { bug!() };
|
||||
|
||||
// A fast path for a common case with closure input/output types.
|
||||
if let ty::Infer(_) = user_ty.kind() {
|
||||
self.eq_types(user_ty, mir_ty, Locations::All(span), ConstraintCategory::Boring)
|
||||
.unwrap();
|
||||
return;
|
||||
}
|
||||
|
||||
let mir_ty = self.normalize(mir_ty, Locations::All(span));
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
let param_env = self.param_env;
|
||||
let op = |infcx: &'_ _| {
|
||||
let ocx = ObligationCtxt::new_in_snapshot(infcx);
|
||||
let user_ty = ocx.normalize(&cause, param_env, user_ty);
|
||||
ocx.eq(&cause, param_env, user_ty, mir_ty)?;
|
||||
if !ocx.select_all_or_error().is_empty() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
Ok(InferOk { value: (), obligations: vec![] })
|
||||
};
|
||||
|
||||
self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::Boring,
|
||||
type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()),
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
span_mirbug!(
|
||||
self,
|
||||
span,
|
||||
"ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
@ -18,6 +18,52 @@ use crate::universal_regions::UniversalRegions;
|
||||
use super::{Locations, TypeChecker};
|
||||
|
||||
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
/// Check explicit closure signature annotation,
|
||||
/// e.g., `|x: FxHashMap<_, &'static u32>| ...`.
|
||||
#[instrument(skip(self, body), level = "debug")]
|
||||
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
|
||||
let mir_def_id = body.source.def_id().expect_local();
|
||||
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
|
||||
return;
|
||||
}
|
||||
let Some(user_provided_poly_sig) =
|
||||
self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Instantiate the canonicalized variables from user-provided signature
|
||||
// (e.g., the `_` in the code above) with fresh variables.
|
||||
// Then replace the bound items in the fn sig with fresh variables,
|
||||
// so that they represent the view from "inside" the closure.
|
||||
let user_provided_sig = self
|
||||
.instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig);
|
||||
let user_provided_sig = self.infcx.replace_bound_vars_with_fresh_vars(
|
||||
body.span,
|
||||
LateBoundRegionConversionTime::FnCall,
|
||||
user_provided_sig,
|
||||
);
|
||||
|
||||
for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip(
|
||||
// In MIR, closure args begin with an implicit `self`. Skip it!
|
||||
body.args_iter().skip(1).map(|local| &body.local_decls[local]),
|
||||
) {
|
||||
self.ascribe_user_type_skip_wf(
|
||||
arg_decl.ty,
|
||||
ty::UserType::Ty(user_ty),
|
||||
arg_decl.source_info.span,
|
||||
);
|
||||
}
|
||||
|
||||
// If the user explicitly annotated the output type, enforce it.
|
||||
let output_decl = &body.local_decls[RETURN_PLACE];
|
||||
self.ascribe_user_type_skip_wf(
|
||||
output_decl.ty,
|
||||
ty::UserType::Ty(user_provided_sig.output()),
|
||||
output_decl.source_info.span,
|
||||
);
|
||||
}
|
||||
|
||||
#[instrument(skip(self, body, universal_regions), level = "debug")]
|
||||
pub(super) fn equate_inputs_and_outputs(
|
||||
&mut self,
|
||||
@ -31,39 +77,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
debug!(?normalized_output_ty);
|
||||
debug!(?normalized_input_tys);
|
||||
|
||||
let mir_def_id = body.source.def_id().expect_local();
|
||||
|
||||
// If the user explicitly annotated the input types, extract
|
||||
// those.
|
||||
//
|
||||
// e.g., `|x: FxHashMap<_, &'static u32>| ...`
|
||||
let user_provided_sig = if !self.tcx().is_closure(mir_def_id.to_def_id()) {
|
||||
None
|
||||
} else {
|
||||
let typeck_results = self.tcx().typeck(mir_def_id);
|
||||
|
||||
typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| {
|
||||
// Instantiate the canonicalized variables from
|
||||
// user-provided signature (e.g., the `_` in the code
|
||||
// above) with fresh variables.
|
||||
let poly_sig = self.instantiate_canonical_with_fresh_inference_vars(
|
||||
body.span,
|
||||
&user_provided_poly_sig,
|
||||
);
|
||||
|
||||
// Replace the bound items in the fn sig with fresh
|
||||
// variables, so that they represent the view from
|
||||
// "inside" the closure.
|
||||
self.infcx.replace_bound_vars_with_fresh_vars(
|
||||
body.span,
|
||||
LateBoundRegionConversionTime::FnCall,
|
||||
poly_sig,
|
||||
)
|
||||
})
|
||||
};
|
||||
|
||||
debug!(?normalized_input_tys, ?body.local_decls);
|
||||
|
||||
// Equate expected input tys with those in the MIR.
|
||||
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
|
||||
if argument_index + 1 >= body.local_decls.len() {
|
||||
@ -86,28 +99,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(user_provided_sig) = user_provided_sig {
|
||||
for (argument_index, &user_provided_input_ty) in
|
||||
user_provided_sig.inputs().iter().enumerate()
|
||||
{
|
||||
// In MIR, closures begin an implicit `self`, so
|
||||
// argument N is stored in local N+2.
|
||||
let local = Local::new(argument_index + 2);
|
||||
let mir_input_ty = body.local_decls[local].ty;
|
||||
let mir_input_span = body.local_decls[local].source_info.span;
|
||||
|
||||
// If the user explicitly annotated the input types, enforce those.
|
||||
let user_provided_input_ty =
|
||||
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
|
||||
|
||||
self.equate_normalized_input_or_output(
|
||||
user_provided_input_ty,
|
||||
mir_input_ty,
|
||||
mir_input_span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
debug!(
|
||||
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
|
||||
body.yield_ty(),
|
||||
@ -153,29 +144,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
terr
|
||||
);
|
||||
};
|
||||
|
||||
// If the user explicitly annotated the output types, enforce those.
|
||||
// Note that this only happens for closures.
|
||||
if let Some(user_provided_sig) = user_provided_sig {
|
||||
let user_provided_output_ty = user_provided_sig.output();
|
||||
let user_provided_output_ty =
|
||||
self.normalize(user_provided_output_ty, Locations::All(output_span));
|
||||
if let Err(err) = self.eq_types(
|
||||
user_provided_output_ty,
|
||||
mir_output_ty,
|
||||
Locations::All(output_span),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
Location::START,
|
||||
"equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
|
||||
mir_output_ty,
|
||||
user_provided_output_ty,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
@ -38,7 +38,6 @@ use rustc_middle::ty::{
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_trait_selection::traits::query::type_op;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
@ -197,6 +196,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
}
|
||||
|
||||
checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
|
||||
checker.check_signature_annotation(&body);
|
||||
|
||||
liveness::generate(
|
||||
&mut checker,
|
||||
body,
|
||||
@ -391,23 +392,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
check_err(self, promoted_body, ty, promoted_ty);
|
||||
}
|
||||
} else {
|
||||
if let Err(terr) = self.cx.fully_perform_op(
|
||||
locations,
|
||||
ConstraintCategory::Boring,
|
||||
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||
constant.literal.ty(),
|
||||
self.cx.ascribe_user_type(
|
||||
constant.literal.ty(),
|
||||
UserType::TypeOf(
|
||||
uv.def.did,
|
||||
UserSubsts { substs: uv.substs, user_self_ty: None },
|
||||
)),
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
constant,
|
||||
"bad constant type {:?} ({:?})",
|
||||
constant,
|
||||
terr
|
||||
);
|
||||
}
|
||||
),
|
||||
locations.span(&self.cx.body),
|
||||
);
|
||||
}
|
||||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||
let unnormalized_ty = tcx.type_of(static_def_id);
|
||||
@ -1041,58 +1033,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
debug!(?self.user_type_annotations);
|
||||
for user_annotation in self.user_type_annotations {
|
||||
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
|
||||
let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
|
||||
let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
|
||||
debug!(?annotation);
|
||||
match annotation {
|
||||
UserType::Ty(mut ty) => {
|
||||
ty = self.normalize(ty, Locations::All(span));
|
||||
|
||||
if let Err(terr) = self.eq_types(
|
||||
ty,
|
||||
inferred_ty,
|
||||
Locations::All(span),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
user_annotation,
|
||||
"bad user type ({:?} = {:?}): {:?}",
|
||||
ty,
|
||||
inferred_ty,
|
||||
terr
|
||||
);
|
||||
}
|
||||
|
||||
self.prove_predicate(
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())),
|
||||
Locations::All(span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
);
|
||||
}
|
||||
UserType::TypeOf(def_id, user_substs) => {
|
||||
if let Err(terr) = self.fully_perform_op(
|
||||
Locations::All(span),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||
inferred_ty,
|
||||
def_id,
|
||||
user_substs,
|
||||
)),
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
user_annotation,
|
||||
"bad user type AscribeUserType({:?}, {:?} {:?}, type_of={:?}): {:?}",
|
||||
inferred_ty,
|
||||
def_id,
|
||||
user_substs,
|
||||
self.tcx().type_of(def_id),
|
||||
terr,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ascribe_user_type(inferred_ty, annotation, span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,11 +106,12 @@ 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>;
|
||||
/// Returns `AdtDef` if `ty` is an ADT.
|
||||
/// Note that `ty` might be a projection type that needs normalization.
|
||||
/// This used to get the enum variants in scope of the type.
|
||||
/// For example, `Self::A` could refer to an associated type
|
||||
/// or to an enum variant depending on the result of this function.
|
||||
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
|
||||
|
||||
/// Invoked when we encounter an error from some prior pass
|
||||
/// (e.g., resolve) that is translated into a ty-error. This is
|
||||
@ -485,14 +486,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 {
|
||||
@ -1267,7 +1261,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(
|
||||
@ -1832,7 +1826,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.
|
||||
@ -1860,7 +1854,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 Some(adt_def) = self.probe_adt(span, qself_ty) {
|
||||
if adt_def.is_enum() {
|
||||
let variant_def = adt_def
|
||||
.variants()
|
||||
@ -1962,6 +1956,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
|
||||
continue;
|
||||
};
|
||||
let ty::Adt(_, adt_substs) = qself_ty.kind() else {
|
||||
// FIXME(inherent_associated_types)
|
||||
bug!("unimplemented: non-adt self of inherent assoc ty");
|
||||
};
|
||||
let item_substs = self.create_substs_for_associated_item(
|
||||
span,
|
||||
assoc_ty_did,
|
||||
@ -1969,7 +1967,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));
|
||||
}
|
||||
}
|
||||
@ -2066,7 +2063,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(
|
||||
@ -2202,7 +2198,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>(
|
||||
@ -2319,6 +2315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
kind: DefKind,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
) -> Vec<PathSeg> {
|
||||
// We need to extract the type parameters supplied by the user in
|
||||
// the path `path`. Due to the current setup, this is a bit of a
|
||||
@ -2386,8 +2383,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
// Case 2. Reference to a variant constructor.
|
||||
DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
|
||||
let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
|
||||
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
|
||||
let (generics_def_id, index) = if let Some(self_ty) = self_ty {
|
||||
let adt_def = self.probe_adt(span, self_ty).unwrap();
|
||||
debug_assert!(adt_def.is_enum());
|
||||
(adt_def.did(), last)
|
||||
} else if last >= 1 && segments[last - 1].args.is_some() {
|
||||
@ -2463,7 +2460,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
|
||||
@ -2483,7 +2480,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
|
||||
let path_segs =
|
||||
self.def_ids_for_value_path_segments(path.segments, None, kind, def_id);
|
||||
self.def_ids_for_value_path_segments(path.segments, None, kind, def_id, span);
|
||||
let generic_segs: FxHashSet<_> =
|
||||
path_segs.iter().map(|PathSeg(_, index)| index).collect();
|
||||
self.prohibit_generics(
|
||||
@ -2623,7 +2620,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) => {
|
||||
@ -2766,8 +2763,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 {
|
||||
@ -2777,8 +2773,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);
|
||||
|
@ -505,9 +505,9 @@ 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 probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
|
||||
// FIXME(#103640): Should we handle the case where `ty` is a projection?
|
||||
ty.ty_adt_def()
|
||||
}
|
||||
|
||||
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
@ -24,7 +24,7 @@ use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, UserType,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
|
||||
use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
@ -161,47 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
|
||||
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
|
||||
self.write_substs(hir_id, method.substs);
|
||||
|
||||
// When the method is confirmed, the `method.substs` includes
|
||||
// parameters from not just the method, but also the impl of
|
||||
// the method -- in particular, the `Self` type will be fully
|
||||
// resolved. However, those are not something that the "user
|
||||
// specified" -- i.e., those types come from the inferred type
|
||||
// of the receiver, not something the user wrote. So when we
|
||||
// create the user-substs, we want to replace those earlier
|
||||
// types with just the types that the user actually wrote --
|
||||
// that is, those that appear on the *method itself*.
|
||||
//
|
||||
// As an example, if the user wrote something like
|
||||
// `foo.bar::<u32>(...)` -- the `Self` type here will be the
|
||||
// type of `foo` (possibly adjusted), but we don't want to
|
||||
// include that. We want just the `[_, u32]` part.
|
||||
if !method.substs.is_empty() {
|
||||
let method_generics = self.tcx.generics_of(method.def_id);
|
||||
if !method_generics.params.is_empty() {
|
||||
let user_type_annotation = self.probe(|_| {
|
||||
let user_substs = UserSubsts {
|
||||
substs: InternalSubsts::for_item(self.tcx, method.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < method_generics.parent_count {
|
||||
self.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
method.substs[i]
|
||||
}
|
||||
}),
|
||||
user_self_ty: None, // not relevant here
|
||||
};
|
||||
|
||||
self.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
method.def_id,
|
||||
user_substs,
|
||||
))
|
||||
});
|
||||
|
||||
debug!("write_method_call: user_type_annotation={:?}", user_type_annotation);
|
||||
self.write_user_type_annotation(hir_id, user_type_annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_substs(&self, node_id: hir::HirId, substs: SubstsRef<'tcx>) {
|
||||
@ -410,23 +369,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
|
||||
pub fn handle_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 = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
|
||||
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
|
||||
t
|
||||
self.handle_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(super) fn user_substs_for_adt(ty: RawTy<'tcx>) -> UserSubsts<'tcx> {
|
||||
match (ty.raw.kind(), ty.normalized.kind()) {
|
||||
(ty::Adt(_, substs), _) => UserSubsts { substs, user_self_ty: None },
|
||||
(_, ty::Adt(adt, substs)) => UserSubsts {
|
||||
substs,
|
||||
user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: ty.raw }),
|
||||
},
|
||||
_ => bug!("non-adt type {:?}", ty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
|
||||
@ -780,7 +754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
qpath: &'tcx QPath<'tcx>,
|
||||
hir_id: hir::HirId,
|
||||
span: Span,
|
||||
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
|
||||
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
|
||||
debug!(
|
||||
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
|
||||
qpath, hir_id, span
|
||||
@ -803,7 +777,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// to be object-safe.
|
||||
// We manually call `register_wf_obligation` in the success path
|
||||
// below.
|
||||
(<dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself), qself, segment)
|
||||
let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself);
|
||||
(self.handle_raw_ty(span, ty), qself, segment)
|
||||
}
|
||||
QPath::LangItem(..) => {
|
||||
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
|
||||
@ -811,7 +786,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 +794,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 +805,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 +828,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 +965,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn instantiate_value_path(
|
||||
&self,
|
||||
segments: &[hir::PathSegment<'_>],
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<RawTy<'tcx>>,
|
||||
res: Res,
|
||||
span: Span,
|
||||
hir_id: hir::HirId,
|
||||
@ -996,7 +975,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let path_segs = match res {
|
||||
Res::Local(_) | Res::SelfCtor(_) => vec![],
|
||||
Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
|
||||
self, segments, self_ty, kind, def_id,
|
||||
self,
|
||||
segments,
|
||||
self_ty.map(|ty| ty.raw),
|
||||
kind,
|
||||
def_id,
|
||||
span,
|
||||
),
|
||||
_ => bug!("instantiate_value_path on {:?}", res),
|
||||
};
|
||||
@ -1007,8 +991,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 +1011,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,19 +1093,21 @@ 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));
|
||||
match *ty.kind() {
|
||||
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
let (ctor_kind, ctor_def_id) = variant.ctor.unwrap();
|
||||
(Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id), Some(substs))
|
||||
let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id));
|
||||
match ty.normalized.ty_adt_def() {
|
||||
Some(adt_def) if adt_def.has_ctor() => {
|
||||
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
|
||||
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
|
||||
let user_substs = Self::user_substs_for_adt(ty);
|
||||
user_self_ty = user_substs.user_self_ty;
|
||||
(new_res, Some(user_substs.substs))
|
||||
}
|
||||
_ => {
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs",
|
||||
);
|
||||
if let Some(adt_def) = ty.ty_adt_def() {
|
||||
if let Some(adt_def) = ty.normalized.ty_adt_def() {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.help("did you mean to use one of the enum's variants?");
|
||||
@ -1193,7 +1179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
<dyn AstConv<'_>>::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()
|
||||
@ -1225,10 +1211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// If we have a default, then we it doesn't matter that we're not
|
||||
// inferring the type arguments: we provide the default where any
|
||||
// is missing.
|
||||
let default = tcx.bound_type_of(param.def_id);
|
||||
self.fcx
|
||||
.normalize_ty(self.span, default.subst(tcx, substs.unwrap()))
|
||||
.into()
|
||||
tcx.bound_type_of(param.def_id).subst(tcx, substs.unwrap()).into()
|
||||
} else {
|
||||
// If no type arguments were provided, we have to infer them.
|
||||
// This case also occurs as a result of some malformed input, e.g.
|
||||
@ -1250,13 +1233,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let substs = self_ctor_substs.unwrap_or_else(|| {
|
||||
let substs_raw = self_ctor_substs.unwrap_or_else(|| {
|
||||
<dyn AstConv<'_>>::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 +1252,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 +1273,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(_) => {
|
||||
|
@ -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,31 +1231,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Res::Def(DefKind::Variant, _) => match ty.kind() {
|
||||
ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
|
||||
_ => bug!("unexpected type: {:?}", ty),
|
||||
Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
|
||||
Some(adt) => {
|
||||
Some((adt.variant_of_res(def), adt.did(), Self::user_substs_for_adt(ty)))
|
||||
}
|
||||
_ => bug!("unexpected type: {:?}", ty.normalized),
|
||||
},
|
||||
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
|
||||
| Res::SelfTyParam { .. }
|
||||
| Res::SelfTyAlias { .. } => match ty.kind() {
|
||||
ty::Adt(adt, substs) if !adt.is_enum() => {
|
||||
Some((adt.non_enum_variant(), adt.did(), substs))
|
||||
| Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
|
||||
Some(adt) if !adt.is_enum() => {
|
||||
Some((adt.non_enum_variant(), adt.did(), Self::user_substs_for_adt(ty)))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => bug!("unexpected definition: {:?}", def),
|
||||
};
|
||||
|
||||
if let Some((variant, did, substs)) = variant {
|
||||
if let Some((variant, did, ty::UserSubsts { substs, user_self_ty })) = variant {
|
||||
debug!("check_struct_path: did={:?} substs={:?}", did, substs);
|
||||
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
|
||||
|
||||
// Register type annotation.
|
||||
self.write_user_type_annotation_from_substs(hir_id, did, substs, user_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 = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
|
||||
(path.res, ty)
|
||||
(path.res, self.handle_raw_ty(path_span, ty))
|
||||
}
|
||||
QPath::TypeRelative(ref qself, ref segment) => {
|
||||
let ty = self.to_ty(qself);
|
||||
|
||||
let result = <dyn AstConv<'_>>::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.handle_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.handle_raw_ty(path_span, ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,11 +297,14 @@ 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> {
|
||||
if ty.has_escaping_bound_vars() {
|
||||
ty // FIXME: normalization and escaping regions
|
||||
} else {
|
||||
self.normalize(span, ty)
|
||||
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
|
||||
match ty.kind() {
|
||||
ty::Adt(adt_def, _) => Some(*adt_def),
|
||||
// FIXME(#104767): Should we handle bound regions here?
|
||||
ty::Alias(ty::Projection, _) if !ty.has_escaping_bound_vars() => {
|
||||
self.normalize(span, ty).ty_adt_def()
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,7 +312,21 @@ 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) {
|
||||
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
|
||||
// FIXME: normalization and escaping regions
|
||||
let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty };
|
||||
self.write_ty(hir_id, 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>,
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::{self, SubstsRef};
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_middle::ty::{InternalSubsts, UserSubsts, UserType};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use std::iter;
|
||||
@ -372,7 +373,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 +398,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
self.cfcx.var_for_def(self.cfcx.span, param)
|
||||
}
|
||||
}
|
||||
<dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||
|
||||
let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
pick.item.def_id,
|
||||
parent_substs,
|
||||
@ -405,7 +407,47 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
None,
|
||||
&arg_count_correct,
|
||||
&mut MethodSubstsCtxt { cfcx: self, pick, seg },
|
||||
)
|
||||
);
|
||||
|
||||
// When the method is confirmed, the `substs` includes
|
||||
// parameters from not just the method, but also the impl of
|
||||
// the method -- in particular, the `Self` type will be fully
|
||||
// resolved. However, those are not something that the "user
|
||||
// specified" -- i.e., those types come from the inferred type
|
||||
// of the receiver, not something the user wrote. So when we
|
||||
// create the user-substs, we want to replace those earlier
|
||||
// types with just the types that the user actually wrote --
|
||||
// that is, those that appear on the *method itself*.
|
||||
//
|
||||
// As an example, if the user wrote something like
|
||||
// `foo.bar::<u32>(...)` -- the `Self` type here will be the
|
||||
// type of `foo` (possibly adjusted), but we don't want to
|
||||
// include that. We want just the `[_, u32]` part.
|
||||
if !substs.is_empty() && !generics.params.is_empty() {
|
||||
let user_type_annotation = self.probe(|_| {
|
||||
let user_substs = UserSubsts {
|
||||
substs: InternalSubsts::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < generics.parent_count {
|
||||
self.fcx.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
substs[i]
|
||||
}
|
||||
}),
|
||||
user_self_ty: None, // not relevant here
|
||||
};
|
||||
|
||||
self.fcx.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
pick.item.def_id,
|
||||
user_substs,
|
||||
))
|
||||
});
|
||||
|
||||
debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation);
|
||||
self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
|
||||
}
|
||||
|
||||
self.normalize(self.span, substs)
|
||||
}
|
||||
|
||||
fn unify_receivers(
|
||||
|
@ -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<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
|
||||
path_resolution: (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
|
||||
expected: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
|
@ -15,22 +15,19 @@ use rustc_span::source_map::Span;
|
||||
|
||||
pub mod type_op {
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
use crate::ty::subst::UserSubsts;
|
||||
use crate::ty::{Predicate, Ty};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use crate::ty::{Predicate, Ty, UserType};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct AscribeUserType<'tcx> {
|
||||
pub mir_ty: Ty<'tcx>,
|
||||
pub def_id: DefId,
|
||||
pub user_substs: UserSubsts<'tcx>,
|
||||
pub user_ty: UserType<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> AscribeUserType<'tcx> {
|
||||
pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
|
||||
Self { mir_ty, def_id, user_substs }
|
||||
pub fn new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self {
|
||||
Self { mir_ty, user_ty }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,7 +679,7 @@ impl<'tcx> CanonicalUserType<'tcx> {
|
||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||
/// so forth.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
|
@ -4,8 +4,8 @@ use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{ParamEnvAnd, Predicate, ToPredicate};
|
||||
use rustc_middle::ty::{UserSelfTy, UserSubsts};
|
||||
use rustc_middle::ty::{ParamEnvAnd, Predicate};
|
||||
use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtBuilderExt;
|
||||
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
|
||||
@ -50,13 +50,46 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
|
||||
key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
|
||||
span: Option<Span>,
|
||||
) -> Result<(), NoSolution> {
|
||||
let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts();
|
||||
debug!(
|
||||
"type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
|
||||
mir_ty, def_id, user_substs
|
||||
);
|
||||
let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
|
||||
debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
|
||||
let span = span.unwrap_or(DUMMY_SP);
|
||||
match user_ty {
|
||||
UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
|
||||
UserType::TypeOf(def_id, user_substs) => {
|
||||
relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(ocx, param_env, span))]
|
||||
fn relate_mir_and_user_ty<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
mir_ty: Ty<'tcx>,
|
||||
user_ty: Ty<'tcx>,
|
||||
) -> Result<(), NoSolution> {
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
let user_ty = ocx.normalize(&cause, param_env, user_ty);
|
||||
ocx.eq(&cause, param_env, mir_ty, user_ty)?;
|
||||
|
||||
// FIXME(#104764): We should check well-formedness before normalization.
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
|
||||
ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(ocx, param_env, span))]
|
||||
fn relate_mir_and_user_substs<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
mir_ty: Ty<'tcx>,
|
||||
def_id: hir::def_id::DefId,
|
||||
user_substs: UserSubsts<'tcx>,
|
||||
) -> Result<(), NoSolution> {
|
||||
let UserSubsts { user_self_ty, substs } = user_substs;
|
||||
let tcx = ocx.infcx.tcx;
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
@ -91,13 +124,13 @@ 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);
|
||||
|
||||
ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
|
||||
|
||||
let predicate: Predicate<'tcx> =
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())).to_predicate(tcx);
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
|
||||
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
|
||||
}
|
||||
|
||||
@ -112,8 +145,7 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
|
||||
// them? This would only be relevant if some input
|
||||
// type were ill-formed but did not appear in `ty`,
|
||||
// which...could happen with normalization...
|
||||
let predicate: Predicate<'tcx> =
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx);
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
|
||||
ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -14,14 +14,6 @@ fn foo<T>() {
|
||||
let _: for<'a> fn(<() as Foo<T>>::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<T>>::Type<'a>` is valid, which requires proving
|
||||
|
@ -10,64 +10,5 @@ error: `T` does not live long enough
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `T` does not live long enough
|
||||
--> $DIR/issue-91139.rs:14:12
|
||||
|
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::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<T>>::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<T>>::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<T: 'static>() {
|
||||
| +++++++++
|
||||
|
||||
error: `T` does not live long enough
|
||||
--> $DIR/issue-91139.rs:14:58
|
||||
|
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: `T` does not live long enough
|
||||
--> $DIR/issue-91139.rs:14:58
|
||||
|
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::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<T>>::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<T: 'static>() {
|
||||
| +++++++++
|
||||
|
||||
error: `T` does not live long enough
|
||||
--> $DIR/issue-91139.rs:14:58
|
||||
|
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: `T` does not live long enough
|
||||
--> $DIR/issue-91139.rs:14:58
|
||||
|
|
||||
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
||||
|
@ -7,6 +7,7 @@ trait SomeTrait<'a> {
|
||||
fn give_me_ice<T>() {
|
||||
callee::<fn(&()) -> <T as SomeTrait<'_>>::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<T: Fn<(&'static (),)>>() {
|
||||
|
@ -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::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn give_me_ice<T: for<'a> 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<T: for<'a> 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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | fn uninit<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let x: &'static &'a ();
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:11:12
|
||||
@ -14,7 +14,7 @@ LL | fn var_type<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let x: &'static &'a () = &&();
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:15:12
|
||||
@ -22,7 +22,7 @@ error: lifetime may not live long enough
|
||||
LL | fn uninit_infer<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let x: &'static &'a _;
|
||||
| ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:21:12
|
||||
@ -31,7 +31,7 @@ LL | fn infer<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let x: &'static &'a _ = &&();
|
||||
| ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:26:12
|
||||
@ -40,7 +40,7 @@ LL | fn uninit_no_var<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let _: &'static &'a ();
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:31:12
|
||||
@ -49,7 +49,7 @@ LL | fn no_var<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let _: &'static &'a () = &&();
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:36:12
|
||||
@ -58,7 +58,7 @@ LL | fn infer_no_var<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let _: &'static &'a _ = &&();
|
||||
| ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/wf-unreachable.rs:49:12
|
||||
@ -67,7 +67,7 @@ LL | fn required_substs<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | return;
|
||||
LL | let _: C<'static, 'a, _> = C((), &(), &());
|
||||
| ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
| ^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -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() {}
|
||||
|
10
src/test/ui/nll/user-annotations/ascribed-type-wf.stderr
Normal file
10
src/test/ui/nll/user-annotations/ascribed-type-wf.stderr
Normal file
@ -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
|
||||
|
15
src/test/ui/nll/user-annotations/closure-sig.rs
Normal file
15
src/test/ui/nll/user-annotations/closure-sig.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// This test fails if #104478 is fixed before #104477.
|
||||
|
||||
// check-pass
|
||||
|
||||
struct Printer<'a, 'b>(&'a (), &'b ());
|
||||
|
||||
impl Printer<'_, '_> {
|
||||
fn test(self) {
|
||||
let clo = |_: &'_ Self| {};
|
||||
clo(&self);
|
||||
clo(&self);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
152
src/test/ui/nll/user-annotations/normalization-2.rs
Normal file
152
src/test/ui/nll/user-annotations/normalization-2.rs
Normal file
@ -0,0 +1,152 @@
|
||||
// Make sure we honor region constraints when normalizing type annotations.
|
||||
|
||||
// check-fail
|
||||
|
||||
#![feature(more_qualified_paths)]
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T> Trait for T
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
type Assoc = MyTy<()>;
|
||||
}
|
||||
|
||||
enum MyTy<T> {
|
||||
Unit,
|
||||
Tuple(),
|
||||
Struct {},
|
||||
Dumb(T),
|
||||
}
|
||||
|
||||
impl<T> MyTy<T> {
|
||||
const CONST: () = ();
|
||||
fn method<X>() {}
|
||||
fn method2<X>(&self) {}
|
||||
}
|
||||
|
||||
trait TraitAssoc {
|
||||
const TRAIT_CONST: ();
|
||||
fn trait_method<X>(&self);
|
||||
}
|
||||
impl<T> TraitAssoc for T {
|
||||
const TRAIT_CONST: () = ();
|
||||
fn trait_method<X>(&self) {}
|
||||
}
|
||||
|
||||
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<Ty<'b>> { None };
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
<Ty<'a>>::method::<Ty<'static>>;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'static>>::method::<Ty<'b>>;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
|
||||
<Ty<'c>>::trait_method::<Ty<'static>>;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'static>>::trait_method::<Ty<'d>>;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
|
||||
<Ty<'e>>::CONST;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'f>>::TRAIT_CONST;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
|
||||
<Ty<'static>>::method::<Ty<'static>>;
|
||||
<Ty<'static>>::trait_method::<Ty<'static>>;
|
||||
<Ty<'static>>::CONST;
|
||||
<Ty<'static>>::TRAIT_CONST;
|
||||
|
||||
MyTy::Unit::<Ty<'g>>;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
MyTy::<Ty<'h>>::Unit;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_call<'a, 'b, 'c>() {
|
||||
<Ty<'a>>::method::<Ty<'static>>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'static>>::method::<Ty<'b>>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_variants<'a, 'b, 'c>() {
|
||||
<Ty<'a>>::Struct {};
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'b>>::Tuple();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'c>>::Unit;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_method_call<'a, 'b>(x: MyTy<()>) {
|
||||
x.method2::<Ty<'a>>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
x.trait_method::<Ty<'b>>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
struct Struct<T> { x: Option<T>, }
|
||||
|
||||
trait Project {
|
||||
type Struct;
|
||||
type Enum;
|
||||
}
|
||||
impl<T> Project for T {
|
||||
type Struct = Struct<()>;
|
||||
type Enum = MyTy<()>;
|
||||
}
|
||||
|
||||
// Resolves to enum variant
|
||||
MyTy::<Ty<'a>>::Struct {}; // without SelfTy
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'b> as Project>::Enum::Struct {}; // with SelfTy
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
|
||||
// Resolves to struct and associated type respectively
|
||||
Struct::<Ty<'c>> { x: None, }; // without SelfTy
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'d> as Project>::Struct { x: None, }; // with SelfTy
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
use MyTy::*;
|
||||
match MyTy::Unit {
|
||||
Struct::<Ty<'a>> {..} => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
Tuple::<Ty<'b>> (..) => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
Unit::<Ty<'c>> => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
Dumb(_) => {},
|
||||
};
|
||||
match MyTy::Unit {
|
||||
<Ty<'d>>::Struct {..} => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'e>>::Tuple (..) => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
<Ty<'f>>::Unit => {},
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
Dumb(_) => {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
296
src/test/ui/nll/user-annotations/normalization-2.stderr
Normal file
296
src/test/ui/nll/user-annotations/normalization-2.stderr
Normal file
@ -0,0 +1,296 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:43: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:48: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:50:11
|
||||
|
|
||||
LL | fn test_closure_sig<'a, 'b>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | || -> Option<Ty<'b>> { 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:55:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | <Ty<'a>>::method::<Ty<'static>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:57:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | <Ty<'static>>::method::<Ty<'b>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:60:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'c` defined here
|
||||
...
|
||||
LL | <Ty<'c>>::trait_method::<Ty<'static>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:62:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'d` defined here
|
||||
...
|
||||
LL | <Ty<'static>>::trait_method::<Ty<'d>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:65:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'e` defined here
|
||||
...
|
||||
LL | <Ty<'e>>::CONST;
|
||||
| ^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:67:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'f` defined here
|
||||
...
|
||||
LL | <Ty<'f>>::TRAIT_CONST;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'f` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:75:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'g` defined here
|
||||
...
|
||||
LL | MyTy::Unit::<Ty<'g>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'g` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:77:5
|
||||
|
|
||||
LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
|
||||
| -- lifetime `'h` defined here
|
||||
...
|
||||
LL | MyTy::<Ty<'h>>::Unit;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'h` 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`
|
||||
= help: replace `'d` with `'static`
|
||||
= help: replace `'e` with `'static`
|
||||
= help: replace `'f` with `'static`
|
||||
= help: replace `'g` with `'static`
|
||||
= help: replace `'h` with `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:82:5
|
||||
|
|
||||
LL | fn test_call<'a, 'b, 'c>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | <Ty<'a>>::method::<Ty<'static>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:84:5
|
||||
|
|
||||
LL | fn test_call<'a, 'b, 'c>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | <Ty<'static>>::method::<Ty<'b>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:89:5
|
||||
|
|
||||
LL | fn test_variants<'a, 'b, 'c>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | <Ty<'a>>::Struct {};
|
||||
| ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:91:5
|
||||
|
|
||||
LL | fn test_variants<'a, 'b, 'c>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | <Ty<'b>>::Tuple();
|
||||
| ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:93:5
|
||||
|
|
||||
LL | fn test_variants<'a, 'b, 'c>() {
|
||||
| -- lifetime `'c` defined here
|
||||
...
|
||||
LL | <Ty<'c>>::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:98:7
|
||||
|
|
||||
LL | fn test_method_call<'a, 'b>(x: MyTy<()>) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | x.method2::<Ty<'a>>();
|
||||
| ^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:100:7
|
||||
|
|
||||
LL | fn test_method_call<'a, 'b>(x: MyTy<()>) {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | x.trait_method::<Ty<'b>>();
|
||||
| ^^^^^^^^^^^^ 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:117:5
|
||||
|
|
||||
LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | MyTy::<Ty<'a>>::Struct {}; // without SelfTy
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:119:5
|
||||
|
|
||||
LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | <Ty<'b> as Project>::Enum::Struct {}; // with SelfTy
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:123:5
|
||||
|
|
||||
LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
| -- lifetime `'c` defined here
|
||||
...
|
||||
LL | Struct::<Ty<'c>> { x: None, }; // without SelfTy
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:125:5
|
||||
|
|
||||
LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
|
||||
| -- lifetime `'d` defined here
|
||||
...
|
||||
LL | <Ty<'d> as Project>::Struct { x: None, }; // with SelfTy
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` 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`
|
||||
= help: replace `'d` with `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:132:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | Struct::<Ty<'a>> {..} => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:134:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'b` defined here
|
||||
...
|
||||
LL | Tuple::<Ty<'b>> (..) => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:136:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'c` defined here
|
||||
...
|
||||
LL | Unit::<Ty<'c>> => {},
|
||||
| ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:141:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'d` defined here
|
||||
...
|
||||
LL | <Ty<'d>>::Struct {..} => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:143:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'e` defined here
|
||||
...
|
||||
LL | <Ty<'e>>::Tuple (..) => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-2.rs:145:9
|
||||
|
|
||||
LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
|
||||
| -- lifetime `'f` defined here
|
||||
...
|
||||
LL | <Ty<'f>>::Unit => {},
|
||||
| ^^^^^^^^^^^^^^ requires that `'f` 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`
|
||||
= help: replace `'d` with `'static`
|
||||
= help: replace `'e` with `'static`
|
||||
= help: replace `'f` with `'static`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
22
src/test/ui/nll/user-annotations/normalization-default.rs
Normal file
22
src/test/ui/nll/user-annotations/normalization-default.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// check-fail
|
||||
|
||||
trait Trait { type Assoc; }
|
||||
impl<'a> Trait for &'a () { type Assoc = &'a (); }
|
||||
|
||||
struct MyTuple<T, U = <&'static () as Trait>::Assoc>(T, U);
|
||||
fn test_tuple(x: &(), y: &()) {
|
||||
MyTuple::<_>((), x);
|
||||
//~^ ERROR
|
||||
let _: MyTuple::<_> = MyTuple((), y);
|
||||
//~^ ERROR
|
||||
}
|
||||
|
||||
struct MyStruct<T, U = <&'static () as Trait>::Assoc> { val: (T, U), }
|
||||
fn test_struct(x: &(), y: &()) {
|
||||
MyStruct::<_> { val: ((), x) };
|
||||
//~^ ERROR
|
||||
let _: MyStruct::<_> = MyStruct { val: ((), y) };
|
||||
//~^ ERROR
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,36 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-default.rs:8:22
|
||||
|
|
||||
LL | fn test_tuple(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | MyTuple::<_>((), x);
|
||||
| ^ this usage requires that `'1` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-default.rs:10:12
|
||||
|
|
||||
LL | fn test_tuple(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'2`
|
||||
...
|
||||
LL | let _: MyTuple::<_> = MyTuple((), y);
|
||||
| ^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-default.rs:16:26
|
||||
|
|
||||
LL | fn test_struct(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | MyStruct::<_> { val: ((), x) };
|
||||
| ^^^^^^^ this usage requires that `'1` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-default.rs:18:12
|
||||
|
|
||||
LL | fn test_struct(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'2`
|
||||
...
|
||||
LL | let _: MyStruct::<_> = MyStruct { val: ((), y) };
|
||||
| ^^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
40
src/test/ui/nll/user-annotations/normalization-infer.rs
Normal file
40
src/test/ui/nll/user-annotations/normalization-infer.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Annnotations may contain projection types with inference variables as input.
|
||||
// Make sure we don't get ambiguities when normalizing them.
|
||||
|
||||
// check-fail
|
||||
|
||||
// Single impl.
|
||||
fn test1<A, B, C, D>(a: A, b: B, c: C) {
|
||||
trait Tr { type Ty; }
|
||||
impl<T: 'static> Tr for (T,) { type Ty = T; }
|
||||
|
||||
let _: <(_,) as Tr>::Ty = a; //~ ERROR type `A`
|
||||
Some::<<(_,) as Tr>::Ty>(b); //~ ERROR type `B`
|
||||
|| -> <(_,) as Tr>::Ty { c }; //~ ERROR type `C`
|
||||
|d: <(_,) as Tr>::Ty| -> D { d }; //~ ERROR type `D`
|
||||
}
|
||||
|
||||
|
||||
// Two impls. The selected impl depends on the actual type.
|
||||
fn test2<A, B, C>(a: A, b: B, c: C) {
|
||||
trait Tr { type Ty; }
|
||||
impl<T: 'static> Tr for (u8, T) { type Ty = T; }
|
||||
impl<T> Tr for (i8, T) { type Ty = T; }
|
||||
type Alias<X, Y> = (<(X, Y) as Tr>::Ty, X);
|
||||
|
||||
fn temp() -> String { todo!() }
|
||||
|
||||
// `u8` impl, requires static.
|
||||
let _: Alias<_, _> = (a, 0u8); //~ ERROR type `A`
|
||||
Some::<Alias<_, _>>((b, 0u8)); //~ ERROR type `B`
|
||||
|| -> Alias<_, _> { (c, 0u8) }; //~ ERROR type `C`
|
||||
|
||||
let _: Alias<_, _> = (&temp(), 0u8); //~ ERROR temporary value
|
||||
Some::<Alias<_, _>>((&temp(), 0u8)); //~ ERROR temporary value
|
||||
|
||||
// `i8` impl, no region constraints.
|
||||
let _: Alias<_, _> = (&temp(), 0i8);
|
||||
Some::<Alias<_, _>>((&temp(), 0i8));
|
||||
}
|
||||
|
||||
fn main() {}
|
101
src/test/ui/nll/user-annotations/normalization-infer.stderr
Normal file
101
src/test/ui/nll/user-annotations/normalization-infer.stderr
Normal file
@ -0,0 +1,101 @@
|
||||
error[E0310]: the parameter type `A` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:11:12
|
||||
|
|
||||
LL | let _: <(_,) as Tr>::Ty = a;
|
||||
| ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test1<A: 'static, B, C, D>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `B` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:12:5
|
||||
|
|
||||
LL | Some::<<(_,) as Tr>::Ty>(b);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test1<A, B: 'static, C, D>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `C` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:13:11
|
||||
|
|
||||
LL | || -> <(_,) as Tr>::Ty { c };
|
||||
| ^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test1<A, B, C: 'static, D>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `D` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:14:6
|
||||
|
|
||||
LL | |d: <(_,) as Tr>::Ty| -> D { d };
|
||||
| ^ ...so that the type `D` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test1<A, B, C, D: 'static>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `A` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:28:12
|
||||
|
|
||||
LL | let _: Alias<_, _> = (a, 0u8);
|
||||
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test2<A: 'static, B, C>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `B` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:29:5
|
||||
|
|
||||
LL | Some::<Alias<_, _>>((b, 0u8));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test2<A, B: 'static, C>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `C` may not live long enough
|
||||
--> $DIR/normalization-infer.rs:30:11
|
||||
|
|
||||
LL | || -> Alias<_, _> { (c, 0u8) };
|
||||
| ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test2<A, B, C: 'static>(a: A, b: B, c: C) {
|
||||
| +++++++++
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/normalization-infer.rs:32:28
|
||||
|
|
||||
LL | let _: Alias<_, _> = (&temp(), 0u8);
|
||||
| ----------- ^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/normalization-infer.rs:33:27
|
||||
|
|
||||
LL | Some::<Alias<_, _>>((&temp(), 0u8));
|
||||
| --^^^^^^------ - temporary value is freed at the end of this statement
|
||||
| | |
|
||||
| | creates a temporary value which is freed while still in use
|
||||
| this usage requires that borrow lasts for `'static`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0310, E0716.
|
||||
For more information about an error, try `rustc --explain E0310`.
|
26
src/test/ui/nll/user-annotations/normalization-self.rs
Normal file
26
src/test/ui/nll/user-annotations/normalization-self.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// check-fail
|
||||
|
||||
trait Trait { type Assoc; }
|
||||
impl<'a> Trait for &'a () { type Assoc = &'a (); }
|
||||
|
||||
struct MyTuple<T>(T);
|
||||
impl MyTuple<<&'static () as Trait>::Assoc> {
|
||||
fn test(x: &(), y: &()) {
|
||||
Self(x);
|
||||
//~^ ERROR
|
||||
let _: Self = MyTuple(y);
|
||||
//~^ ERROR
|
||||
}
|
||||
}
|
||||
|
||||
struct MyStruct<T> { val: T, }
|
||||
impl MyStruct<<&'static () as Trait>::Assoc> {
|
||||
fn test(x: &(), y: &()) {
|
||||
Self { val: x };
|
||||
//~^ ERROR
|
||||
let _: Self = MyStruct { val: y };
|
||||
//~^ ERROR
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
36
src/test/ui/nll/user-annotations/normalization-self.stderr
Normal file
36
src/test/ui/nll/user-annotations/normalization-self.stderr
Normal file
@ -0,0 +1,36 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-self.rs:9:14
|
||||
|
|
||||
LL | fn test(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | Self(x);
|
||||
| ^ this usage requires that `'1` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-self.rs:11:16
|
||||
|
|
||||
LL | fn test(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'2`
|
||||
...
|
||||
LL | let _: Self = MyTuple(y);
|
||||
| ^^^^ type annotation requires that `'2` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-self.rs:19:21
|
||||
|
|
||||
LL | fn test(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | Self { val: x };
|
||||
| ^ this usage requires that `'1` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/normalization-self.rs:21:16
|
||||
|
|
||||
LL | fn test(x: &(), y: &()) {
|
||||
| - let's call the lifetime of this reference `'2`
|
||||
...
|
||||
LL | let _: Self = MyStruct { val: y };
|
||||
| ^^^^ type annotation requires that `'2` must outlive `'static`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -3,8 +3,15 @@
|
||||
|
||||
trait Foo { type Out; }
|
||||
impl Foo for () { type Out = &'static u32; }
|
||||
impl<'a> Foo for &'a () { type Out = &'a u32; }
|
||||
|
||||
fn main() {
|
||||
let a = 22;
|
||||
let b: <() as Foo>::Out = &a; //~ ERROR
|
||||
let _: <() as Foo>::Out = &a; //~ ERROR
|
||||
|
||||
let a = 22;
|
||||
let _: <&'static () as Foo>::Out = &a; //~ ERROR
|
||||
|
||||
let a = 22;
|
||||
let _: <&'_ () as Foo>::Out = &a;
|
||||
}
|
||||
|
@ -1,13 +1,25 @@
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/normalization.rs:9:31
|
||||
--> $DIR/normalization.rs:10:31
|
||||
|
|
||||
LL | let b: <() as Foo>::Out = &a;
|
||||
LL | let _: <() as Foo>::Out = &a;
|
||||
| ---------------- ^^ borrowed value does not live long enough
|
||||
| |
|
||||
| type annotation requires that `a` is borrowed for `'static`
|
||||
...
|
||||
LL | }
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/normalization.rs:13:40
|
||||
|
|
||||
LL | let _: <&'static () as Foo>::Out = &a;
|
||||
| ------------------------- ^^ borrowed value does not live long enough
|
||||
| |
|
||||
| type annotation requires that `a` is borrowed for `'static`
|
||||
...
|
||||
LL | }
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
@ -6,7 +6,7 @@ LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let z: Option<&'b &'a usize> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
@ -19,7 +19,7 @@ LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
|
||||
| lifetime `'a` defined here
|
||||
LL | let y: Paramd<'a> = Paramd { x: a };
|
||||
LL | let z: Option<&'b Paramd<'a>> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
@ -31,7 +31,7 @@ LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let z: Option<&'a &'b usize> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
@ -20,7 +20,7 @@ LL | fn with_assoc_sub<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
@ -20,7 +20,7 @@ LL | fn without_assoc<'a,'b>() {
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
//check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Trait {
|
||||
type Opaque1;
|
||||
type Opaque2;
|
||||
fn constrain(self);
|
||||
}
|
||||
|
||||
impl<'a> Trait for &'a () {
|
||||
type Opaque1 = impl Sized;
|
||||
type Opaque2 = impl Sized + 'a;
|
||||
fn constrain(self) {
|
||||
let _: Self::Opaque1 = ();
|
||||
let _: Self::Opaque2 = self;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -205,7 +205,7 @@ error[E0223]: ambiguous associated type
|
||||
--> $DIR/ufcs-partially-resolved.rs:36:12
|
||||
|
|
||||
LL | let _: <u8 as Tr>::Y::NN;
|
||||
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u16 as Trait>::NN`
|
||||
| ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::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
|
||||
|
Loading…
x
Reference in New Issue
Block a user