mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 22:46:50 +00:00
Auto merge of #89024 - oli-obk:lazy_tait_is_not_limited_to_being_used_in_return_position, r=nikomatsakis
Lazy TAIT preparation cleanups Check that TAIT generics are fully generic in mir typeck instead of wf-check, as wf-check can by definition only check TAIT in return position and not account for TAITs defined in the body of the function r? `@spastorino` `@nikomatsakis`
This commit is contained in:
commit
2b862bed98
@ -1,5 +1,9 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::opaque_types::InferCtxtExt;
|
||||
@ -50,13 +54,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn infer_opaque_types(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
|
||||
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
|
||||
span: Span,
|
||||
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
|
||||
opaque_ty_decls
|
||||
.into_iter()
|
||||
.map(|(opaque_type_key, concrete_type)| {
|
||||
.filter_map(|(opaque_type_key, decl)| {
|
||||
let substs = opaque_type_key.substs;
|
||||
let concrete_type = decl.concrete_ty;
|
||||
debug!(?concrete_type, ?substs);
|
||||
|
||||
let mut subst_regions = vec![self.universal_regions.fr_static];
|
||||
@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
universal_concrete_type,
|
||||
span,
|
||||
);
|
||||
(opaque_type_key, remapped_type)
|
||||
|
||||
check_opaque_type_parameter_valid(
|
||||
infcx.tcx,
|
||||
opaque_type_key,
|
||||
OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
|
||||
)
|
||||
.then_some((opaque_type_key, remapped_type))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -119,3 +130,95 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn check_opaque_type_parameter_valid(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_type_key: OpaqueTypeKey<'_>,
|
||||
decl: OpaqueTypeDecl<'_>,
|
||||
) -> bool {
|
||||
match decl.origin {
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
//
|
||||
// fn foo<P0..Pn>() -> impl Trait
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type Foo<P0...Pn>
|
||||
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
|
||||
//
|
||||
// For lifetime parameters we convert
|
||||
//
|
||||
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type foo::<'p0..'pn>::Foo<'q0..'qm>
|
||||
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
|
||||
//
|
||||
// which would error here on all of the `'static` args.
|
||||
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
|
||||
// Check these
|
||||
OpaqueTyOrigin::TyAlias => {}
|
||||
}
|
||||
let span = decl.definition_span;
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(ty::ReStatic) => {
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_label(
|
||||
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
|
||||
"cannot use static lifetime; use a bound lifetime \
|
||||
instead or remove the lifetime parameter from the \
|
||||
opaque type",
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
seen_params.entry(arg).or_default().push(i);
|
||||
} else {
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(
|
||||
tcx.def_span(opaque_param.def_id),
|
||||
&format!(
|
||||
"used non-generic {} `{}` for generic parameter",
|
||||
opaque_param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||
.collect();
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, &format!("{} used multiple times", descr))
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{
|
||||
@ -193,16 +194,17 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
|
||||
opaque_type_values
|
||||
.into_iter()
|
||||
.filter_map(|(opaque_type_key, decl)| {
|
||||
let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
|
||||
if revealed_ty.has_infer_types_or_consts() {
|
||||
.filter_map(|(opaque_type_key, mut decl)| {
|
||||
decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
|
||||
if decl.concrete_ty.has_infer_types_or_consts() {
|
||||
infcx.tcx.sess.delay_span_bug(
|
||||
body.span,
|
||||
&format!("could not resolve {:#?}", revealed_ty.kind()),
|
||||
&format!("could not resolve {:#?}", decl.concrete_ty.kind()),
|
||||
);
|
||||
revealed_ty = infcx.tcx.ty_error();
|
||||
decl.concrete_ty = infcx.tcx.ty_error();
|
||||
}
|
||||
let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
|
||||
let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
|
||||
{
|
||||
*def_id == opaque_type_key.def_id
|
||||
} else {
|
||||
false
|
||||
@ -234,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
);
|
||||
None
|
||||
} else {
|
||||
Some((opaque_type_key, revealed_ty))
|
||||
Some((opaque_type_key, decl))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
@ -890,7 +892,7 @@ struct BorrowCheckContext<'a, 'tcx> {
|
||||
crate struct MirTypeckResults<'tcx> {
|
||||
crate constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
|
||||
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
|
||||
}
|
||||
|
||||
/// A collection of region constraints that must be satisfied for the
|
||||
|
@ -1062,11 +1062,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
|
||||
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
|
||||
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
|
||||
pub fn may_define_opaque_type(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
opaque_hir_id: hir::HirId,
|
||||
) -> bool {
|
||||
fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
|
||||
let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
|
||||
// Named opaque types can be defined by any siblings or children of siblings.
|
||||
|
@ -2,7 +2,7 @@ use crate::check::{FnCtxt, Inherited};
|
||||
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
@ -12,7 +12,7 @@ use rustc_hir::itemlikevisit::ParItemLikeVisitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::ItemKind;
|
||||
use rustc_middle::hir::map as hir_map;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
|
||||
@ -20,7 +20,6 @@ use rustc_middle::ty::{
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::opaque_types::may_define_opaque_type;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
|
||||
|
||||
@ -77,14 +76,14 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
|
||||
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
|
||||
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
|
||||
/// the types first.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let item = tcx.hir().expect_item(hir_id);
|
||||
|
||||
debug!(
|
||||
"check_item_well_formed(it.def_id={:?}, it.name={})",
|
||||
item.def_id,
|
||||
tcx.def_path_str(def_id.to_def_id())
|
||||
?item.def_id,
|
||||
item.name = ? tcx.def_path_str(def_id.to_def_id())
|
||||
);
|
||||
|
||||
match item.kind {
|
||||
@ -557,8 +556,9 @@ fn check_type_defn<'tcx, F>(
|
||||
});
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx, item))]
|
||||
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
|
||||
debug!("check_trait: {:?}", item.def_id);
|
||||
debug!(?item.def_id);
|
||||
|
||||
let trait_def = tcx.trait_def(item.def_id);
|
||||
if trait_def.is_marker
|
||||
@ -712,13 +712,13 @@ fn check_impl<'tcx>(
|
||||
}
|
||||
|
||||
/// Checks where-clauses and inline bounds that are declared on `def_id`.
|
||||
#[instrument(skip(fcx), level = "debug")]
|
||||
fn check_where_clauses<'tcx, 'fcx>(
|
||||
fcx: &FnCtxt<'fcx, 'tcx>,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
return_ty: Option<(Ty<'tcx>, Span)>,
|
||||
) {
|
||||
debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty);
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
let predicates = tcx.predicates_of(def_id);
|
||||
@ -888,17 +888,15 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
|
||||
let predicates = predicates.instantiate_identity(tcx);
|
||||
|
||||
if let Some((mut return_ty, span)) = return_ty {
|
||||
if let Some((return_ty, _)) = return_ty {
|
||||
if return_ty.has_infer_types_or_consts() {
|
||||
fcx.select_obligations_where_possible(false, |_| {});
|
||||
return_ty = fcx.resolve_vars_if_possible(return_ty);
|
||||
}
|
||||
check_opaque_types(fcx, def_id.expect_local(), span, return_ty);
|
||||
}
|
||||
|
||||
let predicates = fcx.normalize_associated_types_in(span, predicates);
|
||||
|
||||
debug!("check_where_clauses: predicates={:?}", predicates.predicates);
|
||||
debug!(?predicates.predicates);
|
||||
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
||||
let wf_obligations =
|
||||
iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
|
||||
@ -984,143 +982,6 @@ fn check_fn_or_method<'fcx, 'tcx>(
|
||||
check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
|
||||
}
|
||||
|
||||
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
|
||||
/// laid for "higher-order pattern unification".
|
||||
/// This ensures that inference is tractable.
|
||||
/// In particular, definitions of opaque types can only use other generics as arguments,
|
||||
/// and they cannot repeat an argument. Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// type Foo<A, B> = impl Bar<A, B>;
|
||||
///
|
||||
/// // Okay -- `Foo` is applied to two distinct, generic types.
|
||||
/// fn a<T, U>() -> Foo<T, U> { .. }
|
||||
///
|
||||
/// // Not okay -- `Foo` is applied to `T` twice.
|
||||
/// fn b<T>() -> Foo<T, T> { .. }
|
||||
///
|
||||
/// // Not okay -- `Foo` is applied to a non-generic type.
|
||||
/// fn b<T>() -> Foo<T, u32> { .. }
|
||||
/// ```
|
||||
///
|
||||
fn check_opaque_types<'fcx, 'tcx>(
|
||||
fcx: &FnCtxt<'fcx, 'tcx>,
|
||||
fn_def_id: LocalDefId,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
) {
|
||||
trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty);
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
ty.fold_with(&mut ty::fold::BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| {
|
||||
if let ty::Opaque(def_id, substs) = *ty.kind() {
|
||||
trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
|
||||
let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
|
||||
tcx.hir().local_def_id_to_hir_id(local_id)
|
||||
} else {
|
||||
// Opaque types from other crates won't have defining uses in this crate.
|
||||
return ty;
|
||||
};
|
||||
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
|
||||
tcx.hir().expect_item(opaque_hir_id).kind
|
||||
{
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
//
|
||||
// fn foo<P0..Pn>() -> impl Trait
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type Foo<P0...Pn>
|
||||
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
|
||||
//
|
||||
// For lifetime parameters we convert
|
||||
//
|
||||
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type foo::<'p0..'pn>::Foo<'q0..'qm>
|
||||
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
|
||||
//
|
||||
// which would error here on all of the `'static` args.
|
||||
return ty;
|
||||
}
|
||||
if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
|
||||
return ty;
|
||||
}
|
||||
trace!("check_opaque_types: may define, generics={:#?}", generics);
|
||||
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
|
||||
for (i, arg) in substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
|
||||
GenericArgKind::Lifetime(region) if let ty::ReStatic = region => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"non-defining opaque type use in defining scope",
|
||||
)
|
||||
.span_label(
|
||||
tcx.def_span(generics.param_at(i, tcx).def_id),
|
||||
"cannot use static lifetime; use a bound lifetime \
|
||||
instead or remove the lifetime parameter from the \
|
||||
opaque type",
|
||||
)
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
|
||||
GenericArgKind::Lifetime(_) => true,
|
||||
|
||||
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
seen_params.entry(arg).or_default().push(i);
|
||||
} else {
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
let opaque_param = generics.param_at(i, tcx);
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(
|
||||
tcx.def_span(opaque_param.def_id),
|
||||
&format!(
|
||||
"used non-generic {} `{}` for generic parameter",
|
||||
opaque_param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} // for (arg, param)
|
||||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
|
||||
.collect();
|
||||
tcx.sess
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, &format!("{} used multiple times", descr))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
} // if let Opaque
|
||||
ty
|
||||
},
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
});
|
||||
}
|
||||
|
||||
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
|
||||
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
|
||||
of the previous types except `Self`)";
|
||||
@ -1439,20 +1300,23 @@ impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
|
||||
hir_visit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
|
||||
}
|
||||
|
||||
#[instrument(skip(self, i), level = "debug")]
|
||||
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
trace!(?i);
|
||||
self.tcx.ensure().check_item_well_formed(i.def_id);
|
||||
hir_visit::walk_item(self, i);
|
||||
}
|
||||
|
||||
#[instrument(skip(self, trait_item), level = "debug")]
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
||||
debug!("visit_trait_item: {:?}", trait_item);
|
||||
trace!(?trait_item);
|
||||
self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
|
||||
hir_visit::walk_trait_item(self, trait_item);
|
||||
}
|
||||
|
||||
#[instrument(skip(self, impl_item), level = "debug")]
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||
debug!("visit_impl_item: {:?}", impl_item);
|
||||
trace!(?impl_item);
|
||||
self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
|
||||
hir_visit::walk_impl_item(self, impl_item);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, ErrorReported, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
@ -7,7 +6,7 @@ use rustc_hir::intravisit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{HirId, Node};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::symbol::Ident;
|
||||
@ -539,6 +538,25 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
|
||||
/// laid for "higher-order pattern unification".
|
||||
/// This ensures that inference is tractable.
|
||||
/// In particular, definitions of opaque types can only use other generics as arguments,
|
||||
/// and they cannot repeat an argument. Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// type Foo<A, B> = impl Bar<A, B>;
|
||||
///
|
||||
/// // Okay -- `Foo` is applied to two distinct, generic types.
|
||||
/// fn a<T, U>() -> Foo<T, U> { .. }
|
||||
///
|
||||
/// // Not okay -- `Foo` is applied to `T` twice.
|
||||
/// fn b<T>() -> Foo<T, T> { .. }
|
||||
///
|
||||
/// // Not okay -- `Foo` is applied to a non-generic type.
|
||||
/// fn b<T>() -> Foo<T, u32> { .. }
|
||||
/// ```
|
||||
///
|
||||
fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||
use rustc_hir::{Expr, ImplItem, Item, TraitItem};
|
||||
|
||||
@ -584,50 +602,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||
// FIXME(oli-obk): trace the actual span from inference to improve errors.
|
||||
let span = self.tcx.def_span(def_id);
|
||||
|
||||
// HACK(eddyb) this check shouldn't be needed, as `wfcheck`
|
||||
// performs the same checks, in theory, but I've kept it here
|
||||
// using `delay_span_bug`, just in case `wfcheck` slips up.
|
||||
let opaque_generics = self.tcx.generics_of(self.def_id);
|
||||
let mut used_params: FxHashSet<_> = FxHashSet::default();
|
||||
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
if !used_params.insert(arg) {
|
||||
// There was already an entry for `arg`, meaning a generic parameter
|
||||
// was used twice.
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!(
|
||||
"defining opaque type use restricts opaque \
|
||||
type by using the generic parameter `{}` twice",
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let param = opaque_generics.param_at(i, self.tcx);
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
&format!(
|
||||
"defining opaque type use does not fully define opaque type: \
|
||||
generic parameter `{}` is specified as concrete {} `{}`",
|
||||
param.name,
|
||||
param.kind.descr(),
|
||||
arg,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((prev_span, prev_ty)) = self.found {
|
||||
if *concrete_type != prev_ty {
|
||||
if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
|
||||
debug!(?span);
|
||||
// Found different concrete types for the opaque type.
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
|
@ -7,6 +7,7 @@ trait TraitWithAssoc {
|
||||
}
|
||||
|
||||
type Foo<V> = impl Trait<V>;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
trait Trait<U> {}
|
||||
|
||||
@ -14,5 +15,9 @@ impl<W> Trait<W> for () {}
|
||||
|
||||
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR `T` is part of concrete type but not used in parameter list
|
||||
//~| ERROR `T` is part of concrete type but not used in parameter list
|
||||
()
|
||||
}
|
||||
|
@ -1,8 +1,34 @@
|
||||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/bound_reduction2.rs:16:60
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ____________________________________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | ()
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/bound_reduction2.rs:16:60
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ____________________________________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | ()
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:15:46
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
@ -10,5 +36,35 @@ note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `_` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `_` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/bound_reduction2.rs:9:15
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
fn main() {}
|
||||
|
||||
type Two<'a, 'b> = impl std::fmt::Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
|
||||
//~^ ERROR non-defining opaque type use
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_lifetime_param.rs:7:26
|
||||
--> $DIR/generic_duplicate_lifetime_param.rs:8:26
|
||||
|
|
||||
LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
|
||||
| ^^^^^^^^^^^
|
||||
@ -10,5 +10,11 @@ note: lifetime used multiple times
|
||||
LL | type Two<'a, 'b> = impl std::fmt::Debug;
|
||||
| ^^ ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_duplicate_lifetime_param.rs:5:20
|
||||
|
|
||||
LL | type Two<'a, 'b> = impl std::fmt::Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -6,8 +6,11 @@ fn main() {}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
type TwoTys<T, U> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
type TwoLifetimes<'a, 'b> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:12:30
|
||||
--> $DIR/generic_duplicate_param_use.rs:15:30
|
||||
|
|
||||
LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
|
||||
| ^^^^^^^^^^^^
|
||||
@ -10,29 +10,47 @@ note: type used multiple times
|
||||
LL | type TwoTys<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_duplicate_param_use.rs:8:21
|
||||
|
|
||||
LL | type TwoTys<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:17:36
|
||||
--> $DIR/generic_duplicate_param_use.rs:20:36
|
||||
|
|
||||
LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime used multiple times
|
||||
--> $DIR/generic_duplicate_param_use.rs:9:19
|
||||
--> $DIR/generic_duplicate_param_use.rs:10:19
|
||||
|
|
||||
LL | type TwoLifetimes<'a, 'b> = impl Debug;
|
||||
| ^^ ^^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_duplicate_param_use.rs:10:29
|
||||
|
|
||||
LL | type TwoLifetimes<'a, 'b> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use.rs:22:50
|
||||
--> $DIR/generic_duplicate_param_use.rs:25:50
|
||||
|
|
||||
LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: constant used multiple times
|
||||
--> $DIR/generic_duplicate_param_use.rs:10:22
|
||||
--> $DIR/generic_duplicate_param_use.rs:12:22
|
||||
|
|
||||
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_duplicate_param_use.rs:12:50
|
||||
|
|
||||
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -6,6 +6,7 @@ fn main() {}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
type Two<T, U> = impl Debug;
|
||||
//~^ ERROR `T` doesn't implement `Debug`
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use2.rs:10:27
|
||||
--> $DIR/generic_duplicate_param_use2.rs:11:27
|
||||
|
|
||||
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
| ^^^^^^^^^
|
||||
@ -10,5 +10,17 @@ note: type used multiple times
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0277]: `T` doesn't implement `Debug`
|
||||
--> $DIR/generic_duplicate_param_use2.rs:8:18
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -6,6 +6,7 @@ fn main() {}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
type Two<T, U> = impl Debug;
|
||||
//~^ ERROR `T` doesn't implement `Debug`
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
@ -17,5 +18,6 @@ fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
}
|
||||
|
||||
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
u
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use3.rs:10:27
|
||||
--> $DIR/generic_duplicate_param_use3.rs:11:27
|
||||
|
|
||||
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
| ^^^^^^^^^
|
||||
@ -10,5 +10,29 @@ note: type used multiple times
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/generic_duplicate_param_use3.rs:20:1
|
||||
|
|
||||
LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/generic_duplicate_param_use3.rs:16:1
|
||||
|
|
||||
LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `T` doesn't implement `Debug`
|
||||
--> $DIR/generic_duplicate_param_use3.rs:8:18
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -6,6 +6,7 @@ fn main() {}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
type Two<T, U> = impl Debug;
|
||||
//~^ ERROR `U` doesn't implement `Debug`
|
||||
|
||||
fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_duplicate_param_use4.rs:10:27
|
||||
--> $DIR/generic_duplicate_param_use4.rs:11:27
|
||||
|
|
||||
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
|
||||
| ^^^^^^^^^
|
||||
@ -10,5 +10,17 @@ note: type used multiple times
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0277]: `U` doesn't implement `Debug`
|
||||
--> $DIR/generic_duplicate_param_use4.rs:8:18
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
help: consider restricting type parameter `U`
|
||||
|
|
||||
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -5,8 +5,11 @@ use std::fmt::Debug;
|
||||
fn main() {}
|
||||
|
||||
type OneTy<T> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
type OneLifetime<'a> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
type OneConst<const X: usize> = impl Debug;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
// Not defining uses, because they doesn't define *all* possible generics.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:13:21
|
||||
--> $DIR/generic_nondefining_use.rs:16:21
|
||||
|
|
||||
LL | fn concrete_ty() -> OneTy<u32> {
|
||||
| ^^^^^^^^^^
|
||||
@ -10,8 +10,14 @@ note: used non-generic type `u32` for generic parameter
|
||||
LL | type OneTy<T> = impl Debug;
|
||||
| ^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_nondefining_use.rs:7:17
|
||||
|
|
||||
LL | type OneTy<T> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:18:27
|
||||
--> $DIR/generic_nondefining_use.rs:21:27
|
||||
|
|
||||
LL | type OneLifetime<'a> = impl Debug;
|
||||
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
@ -19,17 +25,29 @@ LL | type OneLifetime<'a> = impl Debug;
|
||||
LL | fn concrete_lifetime() -> OneLifetime<'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_nondefining_use.rs:9:24
|
||||
|
|
||||
LL | type OneLifetime<'a> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/generic_nondefining_use.rs:23:24
|
||||
--> $DIR/generic_nondefining_use.rs:26:24
|
||||
|
|
||||
LL | fn concrete_const() -> OneConst<{ 123 }> {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic constant `123_usize` for generic parameter
|
||||
--> $DIR/generic_nondefining_use.rs:9:21
|
||||
--> $DIR/generic_nondefining_use.rs:11:21
|
||||
|
|
||||
LL | type OneConst<const X: usize> = impl Debug;
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: could not find defining uses
|
||||
--> $DIR/generic_nondefining_use.rs:11:33
|
||||
|
|
||||
LL | type OneConst<const X: usize> = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -8,7 +8,6 @@ fn bar() -> Foo {
|
||||
}
|
||||
|
||||
fn baz() -> Foo {
|
||||
//~^ ERROR: concrete type differs from previous defining opaque type use
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
@ -4,18 +4,6 @@ error[E0282]: type annotations needed
|
||||
LL | None
|
||||
| ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/incomplete-inference.rs:10:1
|
||||
|
|
||||
LL | fn baz() -> Foo {
|
||||
| ^^^^^^^^^^^^^^^ expected `[type error]`, got `Option<()>`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/incomplete-inference.rs:5:1
|
||||
|
|
||||
LL | fn bar() -> Foo {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
@ -11,6 +11,7 @@ impl Bug for &() {
|
||||
|
||||
const FUN: fn() -> Self::Item = || ();
|
||||
//~^ ERROR the trait bound `(): Bug` is not satisfied
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -16,7 +16,16 @@ LL | const FUN: fn() -> Self::Item = || ();
|
||||
= help: the following implementations were found:
|
||||
<&() as Bug>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-60371.rs:12:37
|
||||
|
|
||||
LL | impl Bug for &() {
|
||||
| - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
...
|
||||
LL | const FUN: fn() -> Self::Item = || ();
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0658.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -6,6 +6,7 @@ trait IterBits {
|
||||
}
|
||||
|
||||
type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
//~^ ERROR could not find defining uses
|
||||
|
||||
impl<T: Copy, E> IterBits for T
|
||||
where
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-60564.rs:19:34
|
||||
--> $DIR/issue-60564.rs:20:34
|
||||
|
|
||||
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -10,5 +10,11 @@ note: used non-generic type `u8` for generic parameter
|
||||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-60564.rs:8:30
|
||||
|
|
||||
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
// Regression test for issue #68368
|
||||
// Ensures that we don't ICE when emitting an error
|
||||
// for a non-defining use when lifetimes are involved
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Trait<T> {}
|
||||
type Alias<'a, U> = impl Trait<U>;
|
||||
//~^ ERROR could not find defining uses
|
||||
fn f<'a>() -> Alias<'a, ()> {}
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
||||
fn main() {}
|
||||
|
||||
impl<X> Trait<X> for () {}
|
@ -0,0 +1,20 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-68368-non-defining-use-2.rs:9:15
|
||||
|
|
||||
LL | fn f<'a>() -> Alias<'a, ()> {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `()` for generic parameter
|
||||
--> $DIR/issue-68368-non-defining-use-2.rs:7:16
|
||||
|
|
||||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-68368-non-defining-use-2.rs:7:21
|
||||
|
|
||||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Trait<T> {}
|
||||
type Alias<'a, U> = impl Trait<U>;
|
||||
//~^ ERROR could not find defining uses
|
||||
fn f<'a>() -> Alias<'a, ()> {}
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-68368-non-defining-use.rs:8:15
|
||||
--> $DIR/issue-68368-non-defining-use.rs:9:15
|
||||
|
|
||||
LL | fn f<'a>() -> Alias<'a, ()> {}
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -10,5 +10,11 @@ note: used non-generic type `()` for generic parameter
|
||||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: could not find defining uses
|
||||
--> $DIR/issue-68368-non-defining-use.rs:7:21
|
||||
|
|
||||
LL | type Alias<'a, U> = impl Trait<U>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -11,7 +11,6 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>)
|
||||
}
|
||||
|
||||
fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type
|
||||
(a, b)
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
|
||||
--> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
|
||||
|
|
||||
LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
|
||||
| - - found type parameter
|
||||
| |
|
||||
| expected type parameter
|
||||
LL |
|
||||
LL | (a, b)
|
||||
| ^ expected type parameter `A`, found type parameter `B`
|
||||
|
|
||||
@ -14,18 +13,6 @@ LL | (a, b)
|
||||
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
|
||||
|
|
||||
LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
|
||||
|
|
||||
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -5,6 +5,7 @@ use std::fmt::Debug;
|
||||
fn main() {}
|
||||
|
||||
type Two<T, U> = impl Debug;
|
||||
//~^ ERROR `T` doesn't implement `Debug`
|
||||
|
||||
fn two<T: Debug>(t: T) -> Two<T, u32> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
@ -26,6 +27,7 @@ impl Bar for u32 {
|
||||
}
|
||||
|
||||
fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
|
||||
//~^ ERROR concrete type differs from previous
|
||||
(t, <U as Bar>::FOO)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/not_a_defining_use.rs:9:27
|
||||
--> $DIR/not_a_defining_use.rs:10:27
|
||||
|
|
||||
LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
|
||||
| ^^^^^^^^^^^
|
||||
@ -10,5 +10,30 @@ note: used non-generic type `u32` for generic parameter
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/not_a_defining_use.rs:29:1
|
||||
|
|
||||
LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/not_a_defining_use.rs:15:1
|
||||
|
|
||||
LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `T` doesn't implement `Debug`
|
||||
--> $DIR/not_a_defining_use.rs:7:18
|
||||
|
|
||||
LL | type Two<T, U> = impl Debug;
|
||||
| ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Debug` for `(T, i8)`
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
Loading…
Reference in New Issue
Block a user