Auto merge of #102666 - matthiaskrgr:rollup-tuge18t, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #102241 (Package `rust-docs-json` into nightly components (take 3))
 - #102488 (Check generic argument compatibility when projecting assoc ty)
 - #102647 (Only allow ~const bounds for traits with #[const_trait])
 - #102648 (Add test for #102605)
 - #102651 (It's not about types or consts, but the lack of regions)
 - #102653 (resolve instance: missing value to `delay_span_bug`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-10-04 16:29:26 +00:00
commit 01af5040fd
73 changed files with 435 additions and 202 deletions

View File

@ -236,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_infer_types_or_consts() {
if hidden_type.has_non_region_infer() {
infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),

View File

@ -91,14 +91,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) -> Ty<'tcx> {
// No Infer()? Nothing needs doing.
if !ty.has_infer_types_or_consts() {
if !ty.has_non_region_infer() {
debug!("no inference var, nothing needs doing");
return ty;
}
// If `ty` is a type variable, see whether we already know what it is.
ty = self.resolve_vars_if_possible(ty);
if !ty.has_infer_types_or_consts() {
if !ty.has_non_region_infer() {
debug!(?ty);
return ty;
}

View File

@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let get_operand_ty = |expr| {
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.resolve_vars_if_possible(ty);
if ty.has_infer_types_or_consts() {
if ty.has_non_region_infer() {
assert!(self.is_tainted_by_errors());
self.tcx.ty_error()
} else {

View File

@ -149,7 +149,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
target_features: &FxHashSet<Symbol>,
) -> Option<InlineAsmType> {
let ty = (self.get_operand_ty)(expr);
if ty.has_infer_types_or_consts() {
if ty.has_non_region_infer() {
bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty);
}
let asm_ty_isize = match self.tcx.sess.target.pointer_width {

View File

@ -471,7 +471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This has nothing here because it means we did string
// concatenation (e.g., "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted
} else if lhs_ty.has_param_types_or_consts() {
} else if lhs_ty.has_non_region_param() {
// Look for a TraitPredicate in the Fulfillment errors,
// and use it to generate a suggestion.
//
@ -657,7 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("cannot apply unary operator `{}`", op.as_str()),
);
if operand_ty.has_param_types_or_consts() {
if operand_ty.has_non_region_param() {
let predicates = errors.iter().filter_map(|error| {
error.obligation.predicate.to_opt_poly_trait_pred()
});

View File

@ -1428,9 +1428,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_param_types_or_consts()
|| param_count.params.len() > 1
|| has_region
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
{
None
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {

View File

@ -712,9 +712,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> bool {
// Reject any attempt to unify two unevaluated constants that contain inference
// variables, since inference variables in queries lead to ICEs.
if a.substs.has_infer_types_or_consts()
|| b.substs.has_infer_types_or_consts()
|| param_env.has_infer_types_or_consts()
if a.substs.has_non_region_infer()
|| b.substs.has_non_region_infer()
|| param_env.has_non_region_infer()
{
debug!("a or b or param_env contain infer vars in its substs -> cannot unify");
return false;
@ -1734,7 +1734,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Postpone the evaluation of constants whose substs depend on inference
// variables
if substs.has_infer_types_or_consts() {
if substs.has_non_region_infer() {
let ac = AbstractConst::new(self.tcx, unevaluated);
match ac {
Ok(None) => {
@ -2072,21 +2072,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
) -> SubstsRef<'tcx> {
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
match arg.unpack() {
GenericArgKind::Type(_)
if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
{
GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
name: ty::BoundVar::from_usize(idx),
}))
.into()
}
GenericArgKind::Const(ct)
if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
{
GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
let ty = ct.ty();
// If the type references param or infer, replace that too...
if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
if ty.has_non_region_param() || ty.has_non_region_infer() {
bug!("const `{ct}`'s type should not reference params or types");
}
tcx.mk_const(ty::ConstS {

View File

@ -357,7 +357,7 @@ where
// In NLL, we don't have type inference variables
// floating around, so we can do this rather imprecise
// variant of the occurs-check.
assert!(!generalized_ty.has_infer_types_or_consts());
assert!(!generalized_ty.has_non_region_infer());
}
self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);

View File

@ -32,7 +32,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_infer_types_or_consts() {
if !t.has_non_region_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t = self.infcx.shallow_resolve(t);
@ -41,7 +41,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
}
fn fold_const(&mut self, ct: Const<'tcx>) -> Const<'tcx> {
if !ct.has_infer_types_or_consts() {
if !ct.has_non_region_infer() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let ct = self.infcx.shallow_resolve(ct);

View File

@ -45,7 +45,7 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
if ct.substs.has_infer_types_or_consts() {
if ct.substs.has_non_region_infer() {
bug!("did not expect inference variables here");
}
@ -76,7 +76,7 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
if ct.substs.has_infer_types_or_consts() {
if ct.substs.has_non_region_infer() {
bug!("did not expect inference variables here");
}

View File

@ -313,7 +313,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
tainted_by_errors,
};
body.is_polymorphic = body.has_param_types_or_consts();
body.is_polymorphic = body.has_non_region_param();
body
}
@ -339,7 +339,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
tainted_by_errors: None,
};
body.is_polymorphic = body.has_param_types_or_consts();
body.is_polymorphic = body.has_non_region_param();
body
}
@ -2760,7 +2760,7 @@ fn pretty_print_const_value<'tcx>(
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
//
// NB: the `has_param_types_or_consts` check ensures that we can use
// NB: the `has_non_region_param` check ensures that we can use
// the `destructure_const` query with an empty `ty::ParamEnv` without
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
@ -2768,7 +2768,7 @@ fn pretty_print_const_value<'tcx>(
//
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
// correct `ty::ParamEnv` to allow printing *all* constant values.
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
let ct = tcx.lift(ct).unwrap();
let ty = tcx.lift(ty).unwrap();
if let Some(contents) = tcx.try_destructure_mir_constant(

View File

@ -71,16 +71,16 @@ impl<'tcx> AbstractConst<'tcx> {
walk_abstract_const::<!, _>(tcx, self, |node| {
match node.root(tcx) {
Node::Leaf(leaf) => {
if leaf.has_infer_types_or_consts() {
if leaf.has_non_region_infer() {
failure_kind = FailureKind::MentionsInfer;
} else if leaf.has_param_types_or_consts() {
} else if leaf.has_non_region_param() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
}
Node::Cast(_, _, ty) => {
if ty.has_infer_types_or_consts() {
if ty.has_non_region_infer() {
failure_kind = FailureKind::MentionsInfer;
} else if ty.has_param_types_or_consts() {
} else if ty.has_non_region_param() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
}

View File

@ -132,7 +132,7 @@ pub fn simplify_type<'tcx>(
// don't unify with anything else as long as they are fully normalized.
//
// We will have to be careful with lazy normalization here.
TreatParams::AsPlaceholder if !ty.has_infer_types_or_consts() => {
TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
debug!("treating `{}` as a placeholder", ty);
Some(PlaceholderSimplifiedType)
}

View File

@ -244,7 +244,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
debug_assert!(!ty.has_infer_types_or_consts());
debug_assert!(!ty.has_non_region_infer());
// First try computing a static layout.
let err = match tcx.layout_of(param_env.and(ty)) {
@ -260,7 +260,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
ty::Param(_) | ty::Projection(_) => {
debug_assert!(tail.has_param_types_or_consts());
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
_ => bug!(

View File

@ -104,8 +104,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
None
}
}
fn has_param_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
fn has_non_region_param(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
@ -113,8 +113,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
fn has_infer_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
fn has_non_region_infer(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER)
}
fn needs_infer(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_INFER)

View File

@ -290,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.has_param_types_or_consts() {
if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@ -311,7 +311,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
}
fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
if !constant.has_param_types_or_consts() {
if !constant.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@ -336,7 +336,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if !ty.has_param_types_or_consts() {
if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@ -373,7 +373,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.has_param_types_or_consts() {
if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@ -391,7 +391,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if !ty.has_param_types_or_consts() {
if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}

View File

@ -191,32 +191,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
self.tcx.hir()
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
let tcx = self.tcx;
if let hir::ItemKind::Impl(hir::Impl {
constness: hir::Constness::Const,
of_trait: Some(trait_ref),
..
}) = item.kind
&& let Some(def_id) = trait_ref.trait_def_id()
{
let source_map = tcx.sess.source_map();
if !tcx.has_attr(def_id, sym::const_trait) {
tcx.sess
.struct_span_err(
source_map.guess_head_span(item.span),
"const `impl`s must be for traits marked with `#[const_trait]`",
)
.span_note(
source_map.guess_head_span(tcx.def_span(def_id)),
"this trait must be annotated with `#[const_trait]`",
)
.emit();
}
}
intravisit::walk_item(self, item);
}
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
let kind = Some(hir::ConstContext::Const);
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));

View File

@ -301,7 +301,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
// Encode impl generic params if the substitutions contain parameters (implying
// polymorphization is enabled) and this isn't an inherent impl.
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_non_region_param()) {
self = self.path_generic_args(
|this| {
this.path_append_ns(

View File

@ -236,9 +236,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
}
Err(ErrorHandled::TooGeneric) => {
let err = if uv.has_infer_types_or_consts() {
let err = if uv.has_non_region_infer() {
NotConstEvaluatable::MentionsInfer
} else if uv.has_param_types_or_consts() {
} else if uv.has_non_region_param() {
NotConstEvaluatable::MentionsParam
} else {
let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
@ -254,7 +254,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
Ok(_) => {
if uv.substs.has_param_types_or_consts() {
if uv.substs.has_non_region_param() {
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);

View File

@ -661,7 +661,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);
}
}
} else if !trait_ref.has_infer_types_or_consts()
} else if !trait_ref.has_non_region_infer()
&& self.predicate_can_apply(obligation.param_env, trait_ref)
{
// If a where-clause may be useful, remind the
@ -2093,7 +2093,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// Pick the first substitution that still contains inference variables as the one
// we're going to emit an error for. If there are none (see above), fall back to
// a more general error.
let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
let mut err = if let Some(subst) = subst {
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
@ -2323,7 +2323,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
.substs
.iter()
.chain(Some(data.term.into_arg()))
.find(|g| g.has_infer_types_or_consts());
.find(|g| g.has_non_region_infer());
if let Some(subst) = subst {
let mut err = self.emit_inference_failure_err(
body_id,
@ -2352,7 +2352,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
if predicate.references_error() || self.is_tainted_by_errors() {
return;
}
let subst = data.substs.iter().find(|g| g.has_infer_types_or_consts());
let subst = data.substs.iter().find(|g| g.has_non_region_infer());
if let Some(subst) = subst {
let err = self.emit_inference_failure_err(
body_id,

View File

@ -1231,7 +1231,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return;
}
let trait_pred = self.resolve_vars_if_possible(trait_pred);
if trait_pred.has_infer_types_or_consts() {
if trait_pred.has_non_region_infer() {
// Do not ICE while trying to find if a reborrow would succeed on a trait with
// unresolved bindings.
return;

View File

@ -279,7 +279,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
debug!(?obligation, "pre-resolve");
if obligation.predicate.has_infer_types_or_consts() {
if obligation.predicate.has_non_region_infer() {
obligation.predicate =
self.selcx.infcx().resolve_vars_if_possible(obligation.predicate);
}
@ -569,7 +569,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
if c1.has_non_region_infer() || c2.has_non_region_infer() {
ProcessResult::Unchanged
} else {
// Two different constants using generic parameters ~> error.
@ -726,11 +726,11 @@ fn substs_infer_vars<'a, 'tcx>(
.resolve_vars_if_possible(substs)
.skip_binder() // ok because this check doesn't care about regions
.iter()
.filter(|arg| arg.has_infer_types_or_consts())
.filter(|arg| arg.has_non_region_infer())
.flat_map(|arg| {
let mut walker = arg.walk();
while let Some(c) = walker.next() {
if !c.has_infer_types_or_consts() {
if !c.has_non_region_infer() {
walker.visited.remove(&c);
walker.skip_current_subtree();
}

View File

@ -57,7 +57,7 @@ pub fn can_type_implement_copy<'tcx>(
// to begin with, and point to the bad field's span instead.
let cause = if field
.ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
.has_param_types_or_consts()
.has_non_region_param()
{
parent_cause.clone()
} else {

View File

@ -170,7 +170,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
result
);
if result && ty.has_infer_types_or_consts() {
if result && ty.has_non_region_infer() {
// Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm

View File

@ -1488,7 +1488,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
candidate_set.push_candidate(ctor(data));
if potentially_unnormalized_candidates
&& !obligation.predicate.has_infer_types_or_consts()
&& !obligation.predicate.has_non_region_infer()
{
// HACK: Pick the first trait def candidate for a fully
// inferred predicate. This is to allow duplicates that
@ -2146,10 +2146,10 @@ fn confirm_impl_candidate<'cx, 'tcx>(
} else {
ty.map_bound(|ty| ty.into())
};
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl item and trait item have different parameter counts",
"impl item and trait item have different parameters",
);
Progress { term: err.into(), obligations: nested }
} else {
@ -2158,6 +2158,44 @@ fn confirm_impl_candidate<'cx, 'tcx>(
}
}
// Verify that the trait item and its implementation have compatible substs lists
fn check_substs_compatible<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_ty: &ty::AssocItem,
substs: ty::SubstsRef<'tcx>,
) -> bool {
fn check_substs_compatible_inner<'tcx>(
tcx: TyCtxt<'tcx>,
generics: &'tcx ty::Generics,
args: &'tcx [ty::GenericArg<'tcx>],
) -> bool {
if generics.count() != args.len() {
return false;
}
let (parent_args, own_args) = args.split_at(generics.parent_count);
if let Some(parent) = generics.parent
&& let parent_generics = tcx.generics_of(parent)
&& !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
return false;
}
for (param, arg) in std::iter::zip(&generics.params, own_args) {
match (&param.kind, arg.unpack()) {
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
_ => return false,
}
}
true
}
check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
}
fn confirm_impl_trait_in_trait_candidate<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,

View File

@ -174,7 +174,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
let needs_infer = stack.obligation.predicate.has_non_region_infer();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
@ -889,11 +889,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
if obligation.has_param_types_or_consts() {
if obligation.has_non_region_param() {
return;
}
if obligation.has_infer_types_or_consts() {
if obligation.has_non_region_infer() {
candidates.ambiguous = true;
return;
}

View File

@ -728,7 +728,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
if c1.has_non_region_infer() || c2.has_non_region_infer() {
Ok(EvaluatedToAmbig)
} else {
// Two different constants using generic parameters ~> error.
@ -1520,7 +1520,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if !generics.params.is_empty()
&& obligation.predicate.substs[generics.parent_count..]
.iter()
.any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
.any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
{
ProjectionMatchesProjection::Ambiguous
} else {

View File

@ -308,6 +308,32 @@ impl<'tcx> WfPredicates<'tcx> {
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
} else {
if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
if let Some(item) = self.item &&
let hir::ItemKind::Impl(impl_) = item.kind &&
let Some(trait_) = &impl_.of_trait &&
let Some(def_id) = trait_.trait_def_id() &&
def_id == trait_ref.def_id
{
let trait_name = tcx.item_name(def_id);
let mut err = tcx.sess.struct_span_err(
self.span,
&format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"),
);
if def_id.is_local() {
let sp = tcx.def_span(def_id).shrink_to_lo();
err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable);
}
err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`");
err.note("adding a non-const method body in the future would be a breaking change");
err.emit();
} else {
tcx.sess.span_err(
self.span,
"~const can only be applied to `#[const_trait]` traits",
);
}
}
self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
};

View File

@ -79,7 +79,7 @@ fn compute_implied_outlives_bounds<'tcx>(
// implied bounds in some cases, mostly when dealing with projections.
fulfill_cx.register_predicate_obligations(
infcx,
obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
);
// From the full set of obligations, just filter down to the

View File

@ -135,30 +135,30 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
fn expr_is_poly(&mut self, expr: &thir::Expr<'tcx>) -> bool {
if expr.ty.has_param_types_or_consts() {
if expr.ty.has_non_region_param() {
return true;
}
match expr.kind {
thir::ExprKind::NamedConst { substs, .. } => substs.has_param_types_or_consts(),
thir::ExprKind::NamedConst { substs, .. } => substs.has_non_region_param(),
thir::ExprKind::ConstParam { .. } => true,
thir::ExprKind::Repeat { value, count } => {
self.visit_expr(&self.thir()[value]);
count.has_param_types_or_consts()
count.has_non_region_param()
}
_ => false,
}
}
fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool {
if pat.ty.has_param_types_or_consts() {
if pat.ty.has_non_region_param() {
return true;
}
match pat.kind {
thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
thir::PatKind::Constant { value } => value.has_non_region_param(),
thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
lo.has_non_region_param() || hi.has_non_region_param()
}
_ => false,
}

View File

@ -171,9 +171,13 @@ fn resolve_associated_item<'tcx>(
return Ok(None);
}
// If the item does not have a value, then we cannot return an instance.
// Any final impl is required to define all associated items.
if !leaf_def.item.defaultness(tcx).has_value() {
return Ok(None);
let guard = tcx.sess.delay_span_bug(
tcx.def_span(leaf_def.item.def_id),
"missing value for assoc item in impl",
);
return Err(guard);
}
let substs = tcx.erase_regions(substs);

View File

@ -351,7 +351,7 @@ fn layout_of_uncached<'tcx>(
let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
};
debug_assert!(!ty.has_infer_types_or_consts());
debug_assert!(!ty.has_non_region_infer());
Ok(match *ty.kind() {
// Basic scalars.
@ -1688,7 +1688,7 @@ fn record_layout_for_printing_outlined<'tcx>(
// Ignore layouts that are done with non-empty environments or
// non-monomorphic layouts, as the user only wants to see the stuff
// resulting from the final codegen session.
if layout.ty.has_param_types_or_consts() || !cx.param_env.caller_bounds().is_empty() {
if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() {
return;
}

View File

@ -264,7 +264,7 @@ pub trait IntoIterator {
#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ~const Iterator> const IntoIterator for I {
impl<I: Iterator> const IntoIterator for I {
type Item = I::Item;
type IntoIter = I;

View File

@ -799,6 +799,7 @@ impl<T: ?Sized> Unpin for *mut T {}
#[unstable(feature = "const_trait_impl", issue = "67792")]
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[const_trait]
pub trait Destruct {}
/// A marker for tuple types.

View File

@ -1367,6 +1367,7 @@ impl Step for Extended {
}
add_component!("rust-docs" => Docs { host: target });
add_component!("rust-json-docs" => JsonDocs { host: target });
add_component!("rust-demangler"=> RustDemangler { compiler, target });
add_component!("cargo" => Cargo { compiler, target });
add_component!("rustfmt" => Rustfmt { compiler, target });

View File

@ -22,8 +22,8 @@ LL | for i in 0..x {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: ~const Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<I: Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constant functions

View File

@ -7,8 +7,8 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: ~const Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<I: Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants

View File

@ -2,6 +2,7 @@
#![feature(const_trait_impl, generic_const_exprs)]
#[const_trait]
pub trait Tr {
fn a() -> usize;
}

View File

@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
= note: `#[warn(incomplete_features)]` on by default
error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
--> $DIR/constifconst-call-in-const-position.rs:15:38
--> $DIR/constifconst-call-in-const-position.rs:16:38
|
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
| ^^^^^^ calling non-const function `<() as Tr>::a`

View File

@ -0,0 +1,16 @@
trait A {
type B<'b>;
fn a() -> Self::B<'static>;
}
struct C;
struct Wrapper<T>(T);
impl A for C {
type B<T> = Wrapper<T>;
//~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
fn a() -> Self::B<'static> {}
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/issue-102114.rs:11:12
|
LL | type B<'b>;
| -- expected 0 type parameters
...
LL | type B<T> = Wrapper<T>;
| ^ found 1 type parameter
error: aborting due to previous error
For more information about this error, try `rustc --explain E0049`.

View File

@ -0,0 +1,15 @@
// edition:2021
async fn foo() -> Result<(), String> {
Ok(())
}
fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
None
}
fn main() -> Option<()> {
//~^ ERROR `main` has invalid return type `Option<()>`
convert_result(foo())
//~^ ERROR mismatched types
}

View File

@ -0,0 +1,41 @@
error[E0308]: mismatched types
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
| -------------- ^^^^^ expected enum `Result`, found opaque type
| |
| arguments to this function are incorrect
|
note: while checking the return type of the `async fn`
--> $DIR/issue-102605.rs:3:19
|
LL | async fn foo() -> Result<(), String> {
| ^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected enum `Result<(), _>`
found opaque type `impl Future<Output = Result<(), String>>`
note: function defined here
--> $DIR/issue-102605.rs:7:4
|
LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
| ^^^^^^^^^^^^^^ ---------------
help: consider `await`ing on the `Future`
|
LL | convert_result(foo().await)
| ++++++
help: try wrapping the expression in `Err`
|
LL | convert_result(Err(foo()))
| ++++ +
error[E0277]: `main` has invalid return type `Option<()>`
--> $DIR/issue-102605.rs:11:14
|
LL | fn main() -> Option<()> {
| ^^^^^^^^^^ `main` can only return types that implement `Termination`
|
= help: consider using `()`, or a `Result`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

View File

@ -47,8 +47,8 @@ LL | [(); { for _ in 0usize.. {}; 0}];
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: ~const Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<I: Iterator> const IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constants

View File

@ -2,13 +2,18 @@
struct S;
impl PartialEq for S {
#[const_trait]
trait Foo {
fn eq(&self, _: &Self) -> bool;
}
impl Foo for S {
fn eq(&self, _: &S) -> bool {
true
}
}
const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
const fn equals_self<T: ~const Foo>(t: &T) -> bool {
true
}

View File

@ -1,26 +1,21 @@
error[E0277]: can't compare `S` with `S` in const contexts
--> $DIR/call-generic-method-nonconst.rs:18:34
error[E0277]: the trait bound `S: ~const Foo` is not satisfied
--> $DIR/call-generic-method-nonconst.rs:23:34
|
LL | pub const EQ: bool = equals_self(&S);
| ----------- ^^ no implementation for `S == S`
| ----------- ^^ the trait `~const Foo` is not implemented for `S`
| |
| required by a bound introduced by this call
|
= help: the trait `~const PartialEq` is not implemented for `S`
note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
--> $DIR/call-generic-method-nonconst.rs:18:34
note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
--> $DIR/call-generic-method-nonconst.rs:23:34
|
LL | pub const EQ: bool = equals_self(&S);
| ^^
note: required by a bound in `equals_self`
--> $DIR/call-generic-method-nonconst.rs:11:25
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
help: consider annotating `S` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
--> $DIR/call-generic-method-nonconst.rs:16:25
|
LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
| ^^^^^^^^^^ required by this bound in `equals_self`
error: aborting due to previous error

View File

@ -1,5 +1,5 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:43:5
--> $DIR/const-drop-fail.rs:44:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -9,7 +9,7 @@ LL | NonTrivialDrop,
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:45:5
--> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:45:5
--> $DIR/const-drop-fail.rs:46:5
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
--> $DIR/const-drop-fail.rs:47:5
--> $DIR/const-drop-fail.rs:48:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -55,14 +55,14 @@ LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
|
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
--> $DIR/const-drop-fail.rs:28:25
--> $DIR/const-drop-fail.rs:29:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: 1 redundant requirement hidden
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`

View File

@ -19,7 +19,8 @@ impl const Drop for ConstImplWithDropGlue {
fn drop(&mut self) {}
}
trait A { fn a() { println!("A"); } }
#[const_trait]
trait A { fn a() { } }
impl A for NonTrivialDrop {}

View File

@ -1,5 +1,5 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:43:5
--> $DIR/const-drop-fail.rs:44:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -9,7 +9,7 @@ LL | NonTrivialDrop,
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
--> $DIR/const-drop-fail.rs:45:5
--> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $DIR/const-drop-fail.rs:45:5
--> $DIR/const-drop-fail.rs:46:5
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
--> $DIR/const-drop-fail.rs:47:5
--> $DIR/const-drop-fail.rs:48:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@ -55,14 +55,14 @@ LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
|
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
--> $DIR/const-drop-fail.rs:28:25
--> $DIR/const-drop-fail.rs:29:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: 1 redundant requirement hidden
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
--> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`

View File

@ -1,9 +1,9 @@
#![feature(const_trait_impl)]
pub trait A {}
//~^ NOTE: this trait must be annotated with `#[const_trait]`
//~^ HELP: mark `A` as const
impl const A for () {}
//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
fn main() {}

View File

@ -1,14 +1,14 @@
error: const `impl`s must be for traits marked with `#[const_trait]`
--> $DIR/const-impl-requires-const-trait.rs:6:1
|
LL | impl const A for () {}
| ^^^^^^^^^^^^^^^^^^^
|
note: this trait must be annotated with `#[const_trait]`
--> $DIR/const-impl-requires-const-trait.rs:3:1
error: const `impl` for trait `A` which is not marked with `#[const_trait]`
--> $DIR/const-impl-requires-const-trait.rs:6:12
|
LL | pub trait A {}
| ^^^^^^^^^^^
| - help: mark `A` as const: `#[const_trait]`
...
LL | impl const A for () {}
| ^
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
error: aborting due to previous error

View File

@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
#[const_trait]
trait Tr {}
impl Tr for () {}

View File

@ -1,16 +1,16 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-body-checking.rs:11:15
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
|
LL | foo::<()>();
| ^^ the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
--> $DIR/default-method-body-is-const-body-checking.rs:11:15
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
|
LL | foo::<()>();
| ^^
note: required by a bound in `foo`
--> $DIR/default-method-body-is-const-body-checking.rs:6:28
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
LL | const fn foo<T>() where T: ~const Tr {}
| ^^^^^^^^^ required by this bound in `foo`

View File

@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-2.rs:11:12
|
LL | trait Bar: ~const Foo {}
| ^^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-2.rs:11:12
|
LL | trait Bar: ~const Foo {}
| ^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,14 +1,19 @@
#![feature(const_trait_impl)]
// revisions: yy yn ny nn
#[cfg_attr(any(yy, yn), const_trait)]
trait Foo {
fn a(&self);
}
#[cfg_attr(any(yy, ny), const_trait)]
trait Bar: ~const Foo {}
//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
const fn foo<T: Bar>(x: &T) {
x.a();
//~^ ERROR the trait bound
//~| ERROR cannot call
//[yn,yy]~^ ERROR the trait bound
}
fn main() {}

View File

@ -1,24 +0,0 @@
error[E0277]: the trait bound `T: ~const Foo` is not satisfied
--> $DIR/super-traits-fail-2.rs:9:7
|
LL | x.a();
| ^^^ the trait `~const Foo` is not implemented for `T`
|
note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
--> $DIR/super-traits-fail-2.rs:9:7
|
LL | x.a();
| ^^^
error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
--> $DIR/super-traits-fail-2.rs:9:7
|
LL | x.a();
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -0,0 +1,21 @@
error[E0277]: the trait bound `T: ~const Foo` is not satisfied
--> $DIR/super-traits-fail-2.rs:15:5
|
LL | x.a();
| ^ - required by a bound introduced by this call
| |
| the trait `~const Foo` is not implemented for `T`
|
note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
--> $DIR/super-traits-fail-2.rs:15:5
|
LL | x.a();
| ^
help: consider further restricting this bound
|
LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
| ++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
error[E0277]: the trait bound `T: ~const Foo` is not satisfied
--> $DIR/super-traits-fail-2.rs:15:5
|
LL | x.a();
| ^ - required by a bound introduced by this call
| |
| the trait `~const Foo` is not implemented for `T`
|
note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
--> $DIR/super-traits-fail-2.rs:15:5
|
LL | x.a();
| ^
help: consider further restricting this bound
|
LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
| ++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,14 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:12
|
LL | trait Bar: ~const Foo {}
| ^^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:15:17
|
LL | const fn foo<T: ~const Bar>(x: &T) {
| ^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:12
|
LL | trait Bar: ~const Foo {}
| ^^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,20 @@
#![feature(const_trait_impl)]
// revisions: yy yn ny nn
//[yy] check-pass
#[cfg_attr(any(yy, yn), const_trait)]
trait Foo {
fn a(&self);
}
#[cfg_attr(any(yy, ny), const_trait)]
trait Bar: ~const Foo {}
//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
const fn foo<T: ~const Bar>(x: &T) {
//[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
x.a();
}
fn main() {}

View File

@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:15:17
|
LL | const fn foo<T: ~const Bar>(x: &T) {
| ^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,6 +1,7 @@
#![feature(const_trait_impl)]
#![feature(associated_type_bounds)]
#[const_trait]
trait T {}
struct S;
impl T for S {}

View File

@ -1,5 +1,5 @@
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:8:19
--> $DIR/tilde-const-invalid-places.rs:9:19
|
LL | fn rpit() -> impl ~const T { S }
| ^^^^^^^^
@ -7,7 +7,7 @@ LL | fn rpit() -> impl ~const T { S }
= note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:11:17
--> $DIR/tilde-const-invalid-places.rs:12:17
|
LL | fn apit(_: impl ~const T) {}
| ^^^^^^^^
@ -15,7 +15,7 @@ LL | fn apit(_: impl ~const T) {}
= note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:14:50
--> $DIR/tilde-const-invalid-places.rs:15:50
|
LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
| ^^^^^^^^
@ -23,7 +23,7 @@ LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
= note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:17:48
--> $DIR/tilde-const-invalid-places.rs:18:48
|
LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
| ^^^^^^^^
@ -31,7 +31,7 @@ LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
= note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
error: `~const` and `?` are mutually exclusive
--> $DIR/tilde-const-invalid-places.rs:20:25
--> $DIR/tilde-const-invalid-places.rs:21:25
|
LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^

View File

@ -4,8 +4,10 @@
// test is not enough.
#![feature(const_trait_impl)]
#[const_trait]
trait Bar {}
#[const_trait]
trait Foo {
fn a();
fn b() where Self: ~const Bar;

View File

@ -1,11 +1,11 @@
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
--> $DIR/trait-where-clause-const.rs:17:5
--> $DIR/trait-where-clause-const.rs:19:5
|
LL | T::b();
| ^^^^^^ the trait `~const Bar` is not implemented for `T`
|
note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
--> $DIR/trait-where-clause-const.rs:17:5
--> $DIR/trait-where-clause-const.rs:19:5
|
LL | T::b();
| ^^^^^^
@ -15,13 +15,13 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
| ++++++++++++
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
--> $DIR/trait-where-clause-const.rs:19:5
--> $DIR/trait-where-clause-const.rs:21:5
|
LL | T::c::<T>();
| ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
|
note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
--> $DIR/trait-where-clause-const.rs:19:5
--> $DIR/trait-where-clause-const.rs:21:5
|
LL | T::c::<T>();
| ^^^^^^^^^^^

View File

@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
#[const_trait]
trait Foo {
fn bar() where Self: ~const Foo;
}

View File

@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
#[const_trait]
trait Bar {}
trait Foo {

View File

@ -1,11 +1,11 @@
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:13:5
--> $DIR/trait-where-clause.rs:14:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::b`
--> $DIR/trait-where-clause.rs:7:24
--> $DIR/trait-where-clause.rs:8:24
|
LL | fn b() where Self: ~const Bar;
| ^^^^^^^^^^ required by this bound in `Foo::b`
@ -15,13 +15,13 @@ LL | fn test1<T: Foo + Bar>() {
| +++++
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:15:12
--> $DIR/trait-where-clause.rs:16:12
|
LL | T::c::<T>();
| ^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::c`
--> $DIR/trait-where-clause.rs:8:13
--> $DIR/trait-where-clause.rs:9:13
|
LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^ required by this bound in `Foo::c`

View File

@ -193,6 +193,12 @@ macro_rules! t {
Err(e) => panic!("{} failed with {}", stringify!($e), e),
}
};
($e:expr, $extra:expr) => {
match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}: {}", stringify!($e), e, $extra),
}
};
}
struct Builder {
@ -437,7 +443,7 @@ impl Builder {
host_component("rustfmt-preview"),
host_component("llvm-tools-preview"),
host_component("rust-analysis"),
host_component("rust-docs-json"),
host_component("rust-docs-json-preview"),
]);
extensions.extend(
@ -584,7 +590,7 @@ impl Builder {
self.shipped_files.insert(name.clone());
let dst = self.output.join(name);
t!(fs::write(&dst, contents));
t!(fs::write(&dst, contents), format!("failed to create manifest {}", dst.display()));
}
fn write_shipped_files(&self, path: &Path) {

View File

@ -20,6 +20,7 @@ pub(crate) enum PkgType {
Rustfmt,
LlvmTools,
Miri,
JsonDocs,
Other(String),
}
@ -36,6 +37,7 @@ impl PkgType {
"rustfmt" | "rustfmt-preview" => PkgType::Rustfmt,
"llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools,
"miri" | "miri-preview" => PkgType::Miri,
"rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs,
other => PkgType::Other(other.into()),
}
}
@ -53,6 +55,7 @@ impl PkgType {
PkgType::Rustfmt => "rustfmt",
PkgType::LlvmTools => "llvm-tools",
PkgType::Miri => "miri",
PkgType::JsonDocs => "rust-docs-json",
PkgType::Other(component) => component,
}
}
@ -72,6 +75,7 @@ impl PkgType {
PkgType::Rust => true,
PkgType::RustSrc => true,
PkgType::Rustc => true,
PkgType::JsonDocs => true,
PkgType::Other(_) => true,
}
}
@ -113,6 +117,9 @@ impl Versions {
Some(version) => Ok(version.clone()),
None => {
let version_info = self.load_version_from_tarball(package)?;
if *package == PkgType::Rust && version_info.version.is_none() {
panic!("missing version info for toolchain");
}
self.versions.insert(package.clone(), version_info.clone());
Ok(version_info)
}
@ -127,6 +134,7 @@ impl Versions {
Ok(file) => file,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
// Missing tarballs do not return an error, but return empty data.
println!("warning: missing tarball {}", tarball.display());
return Ok(VersionInfo::default());
}
Err(err) => return Err(err.into()),

View File

@ -1238,7 +1238,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
Position::ReborrowStable(precedence).into()
},
ty::Adt(_, substs) if substs.has_param_types_or_consts() => {
ty::Adt(_, substs) if substs.has_non_region_param() => {
TyPosition::new_deref_stable_for_result(precedence, ty)
},
ty::Bool