Auto merge of #103426 - matthiaskrgr:rollup-n6dqdy8, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #103123 (Introduce `subst_iter` and `subst_iter_copied` on `EarlyBinder` ) - #103328 (Do not suggest trivially false const predicates) - #103354 (Escape string literals when fixing overlong char literal) - #103355 (Handle return-position `impl Trait` in traits properly in `register_hidden_type`) - #103368 (Delay ambiguity span bug in normalize query iff not rustdoc) - #103388 (rustdoc: remove unused CSS class `.result-description`) - #103399 (Change `unknown_lint` applicability to `MaybeIncorrect`) - #103401 (Use functions for headings rustdoc GUI test) - #103412 (Fix typo in docs of `String::leak`.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
faab68eb29
45 changed files with 467 additions and 248 deletions
|
@ -664,10 +664,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||||
});
|
});
|
||||||
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
|
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
|
||||||
// Recurse into bounds
|
// Recurse into bounds
|
||||||
for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
|
for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
|
||||||
let pred_span = pred.0.1;
|
|
||||||
|
|
||||||
let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
|
|
||||||
let pred = pred.fold_with(self);
|
let pred = pred.fold_with(self);
|
||||||
let pred = self.ocx.normalize(
|
let pred = self.ocx.normalize(
|
||||||
ObligationCause::misc(self.span, self.body_id),
|
ObligationCause::misc(self.span, self.body_id),
|
||||||
|
@ -1752,15 +1749,10 @@ pub fn check_type_bounds<'tcx>(
|
||||||
|
|
||||||
let obligations = tcx
|
let obligations = tcx
|
||||||
.bound_explicit_item_bounds(trait_ty.def_id)
|
.bound_explicit_item_bounds(trait_ty.def_id)
|
||||||
.transpose_iter()
|
.subst_iter_copied(tcx, rebased_substs)
|
||||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
.map(|(concrete_ty_bound, span)| {
|
||||||
.map(|(bound, span)| {
|
|
||||||
debug!(?bound);
|
|
||||||
// this is where opaque type is found
|
|
||||||
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
|
||||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
||||||
|
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
|
||||||
traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
debug!("check_type_bounds: item_bounds={:?}", obligations);
|
debug!("check_type_bounds: item_bounds={:?}", obligations);
|
||||||
|
|
|
@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ty in [first_ty, second_ty] {
|
for ty in [first_ty, second_ty] {
|
||||||
for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() {
|
for (pred, _) in self
|
||||||
let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs);
|
.tcx
|
||||||
|
.bound_explicit_item_bounds(rpit_def_id)
|
||||||
|
.subst_iter_copied(self.tcx, substs)
|
||||||
|
{
|
||||||
let pred = match pred.kind().skip_binder() {
|
let pred = match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Trait(mut trait_pred) => {
|
ty::PredicateKind::Trait(mut trait_pred) => {
|
||||||
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
|
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
|
||||||
|
|
|
@ -176,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
match *expected_ty.kind() {
|
match *expected_ty.kind() {
|
||||||
ty::Opaque(def_id, substs) => {
|
ty::Opaque(def_id, substs) => {
|
||||||
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
|
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
|
||||||
let sig = bounds
|
let sig =
|
||||||
.transpose_iter()
|
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
|
||||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
.kind()
|
||||||
.find_map(|(pred, span)| match pred.0.kind().skip_binder() {
|
.skip_binder()
|
||||||
|
{
|
||||||
ty::PredicateKind::Projection(proj_predicate) => self
|
ty::PredicateKind::Projection(proj_predicate) => self
|
||||||
.deduce_sig_from_projection(
|
.deduce_sig_from_projection(
|
||||||
Some(span.0),
|
Some(span),
|
||||||
pred.0
|
pred.kind().rebind(proj_predicate),
|
||||||
.kind()
|
|
||||||
.rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
|
|
||||||
),
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let kind = bounds
|
let kind = bounds
|
||||||
.transpose_iter()
|
.0
|
||||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
.iter()
|
||||||
.filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
|
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Trait(tp) => {
|
ty::PredicateKind::Trait(tp) => {
|
||||||
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
|
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
|
||||||
}
|
}
|
||||||
|
@ -697,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ty::Opaque(def_id, substs) => self
|
ty::Opaque(def_id, substs) => self
|
||||||
.tcx
|
.tcx
|
||||||
.bound_explicit_item_bounds(def_id)
|
.bound_explicit_item_bounds(def_id)
|
||||||
.transpose_iter()
|
.subst_iter_copied(self.tcx, substs)
|
||||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
.find_map(|(p, s)| get_future_output(p, s))?,
|
||||||
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
|
|
||||||
ty::Error(_) => return None,
|
ty::Error(_) => return None,
|
||||||
ty::Projection(proj)
|
ty::Projection(proj)
|
||||||
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
|
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
|
||||||
{
|
{
|
||||||
self.tcx
|
self.tcx
|
||||||
.bound_explicit_item_bounds(proj.item_def_id)
|
.bound_explicit_item_bounds(proj.item_def_id)
|
||||||
.transpose_iter()
|
.subst_iter_copied(self.tcx, proj.substs)
|
||||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
.find_map(|(p, s)| get_future_output(p, s))?
|
||||||
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
|
|
||||||
}
|
}
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
self.tcx.def_span(expr_def_id),
|
self.tcx.def_span(expr_def_id),
|
||||||
|
|
|
@ -338,8 +338,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
|
|
||||||
let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
|
let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
|
||||||
|
|
||||||
for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
|
for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) {
|
||||||
let predicate = predicate.subst(self.tcx, substs);
|
|
||||||
let output = predicate
|
let output = predicate
|
||||||
.kind()
|
.kind()
|
||||||
.map_bound(|kind| match kind {
|
.map_bound(|kind| match kind {
|
||||||
|
@ -2272,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
|
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
|
||||||
}
|
}
|
||||||
FailureCode::Error0308(failure_str) => {
|
FailureCode::Error0308(failure_str) => {
|
||||||
|
fn escape_literal(s: &str) -> String {
|
||||||
|
let mut escaped = String::with_capacity(s.len());
|
||||||
|
let mut chrs = s.chars().peekable();
|
||||||
|
while let Some(first) = chrs.next() {
|
||||||
|
match (first, chrs.peek()) {
|
||||||
|
('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push(delim);
|
||||||
|
chrs.next();
|
||||||
|
}
|
||||||
|
('"' | '\'', _) => {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push(first)
|
||||||
|
}
|
||||||
|
(c, _) => escaped.push(c),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
escaped
|
||||||
|
}
|
||||||
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
|
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
|
||||||
if let Some((expected, found)) = trace.values.ty() {
|
if let Some((expected, found)) = trace.values.ty() {
|
||||||
match (expected.kind(), found.kind()) {
|
match (expected.kind(), found.kind()) {
|
||||||
|
@ -2293,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
"if you meant to write a `char` literal, use single quotes",
|
"if you meant to write a `char` literal, use single quotes",
|
||||||
format!("'{}'", code),
|
format!("'{}'", escape_literal(code)),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2308,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
"if you meant to write a `str` literal, use double quotes",
|
"if you meant to write a `str` literal, use double quotes",
|
||||||
format!("\"{}\"", code),
|
format!("\"{}\"", escape_literal(code)),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::errors::OpaqueHiddenTypeDiag;
|
use crate::errors::OpaqueHiddenTypeDiag;
|
||||||
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
|
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
|
use hir::def::DefKind;
|
||||||
use hir::def_id::{DefId, LocalDefId};
|
use hir::def_id::{DefId, LocalDefId};
|
||||||
use hir::{HirId, OpaqueTyOrigin};
|
use hir::{HirId, OpaqueTyOrigin};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
@ -543,16 +544,18 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
|
|
||||||
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
|
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
|
||||||
|
|
||||||
for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
|
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
|
||||||
debug!(?predicate);
|
|
||||||
let predicate = predicate.subst(tcx, substs);
|
|
||||||
|
|
||||||
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||||
tcx,
|
tcx,
|
||||||
ty_op: |ty| match *ty.kind() {
|
ty_op: |ty| match *ty.kind() {
|
||||||
// We can't normalize associated types from `rustc_infer`,
|
// We can't normalize associated types from `rustc_infer`,
|
||||||
// but we can eagerly register inference variables for them.
|
// but we can eagerly register inference variables for them.
|
||||||
ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
|
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
|
||||||
|
ty::Projection(projection_ty)
|
||||||
|
if !projection_ty.has_escaping_bound_vars()
|
||||||
|
&& tcx.def_kind(projection_ty.item_def_id)
|
||||||
|
!= DefKind::ImplTraitPlaceholder =>
|
||||||
|
{
|
||||||
self.infer_projection(
|
self.infer_projection(
|
||||||
param_env,
|
param_env,
|
||||||
projection_ty,
|
projection_ty,
|
||||||
|
@ -568,6 +571,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
{
|
{
|
||||||
hidden_ty
|
hidden_ty
|
||||||
}
|
}
|
||||||
|
// FIXME(RPITIT): This can go away when we move to associated types
|
||||||
|
ty::Projection(proj)
|
||||||
|
if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
|
||||||
|
{
|
||||||
|
hidden_ty
|
||||||
|
}
|
||||||
_ => ty,
|
_ => ty,
|
||||||
},
|
},
|
||||||
lt_op: |lt| lt,
|
lt_op: |lt| lt,
|
||||||
|
|
|
@ -960,7 +960,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
||||||
sp,
|
sp,
|
||||||
"did you mean",
|
"did you mean",
|
||||||
suggestion,
|
suggestion,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
lint
|
lint
|
||||||
|
|
|
@ -91,14 +91,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
||||||
// For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
|
// For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
|
||||||
// e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
|
// e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
|
||||||
// with `impl Send: OtherTrait`.
|
// with `impl Send: OtherTrait`.
|
||||||
for assoc_pred_and_span in
|
for (assoc_pred, assoc_pred_span) in cx
|
||||||
cx.tcx.bound_explicit_item_bounds(proj.projection_ty.item_def_id).transpose_iter()
|
.tcx
|
||||||
|
.bound_explicit_item_bounds(proj.projection_ty.item_def_id)
|
||||||
|
.subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
|
||||||
{
|
{
|
||||||
let assoc_pred_span = assoc_pred_and_span.0.1;
|
let assoc_pred = assoc_pred.fold_with(proj_replacer);
|
||||||
let assoc_pred = assoc_pred_and_span
|
|
||||||
.map_bound(|(pred, _)| *pred)
|
|
||||||
.subst(cx.tcx, &proj.projection_ty.substs)
|
|
||||||
.fold_with(proj_replacer);
|
|
||||||
let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
|
let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -795,8 +795,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
let mut fn_traits = FxIndexMap::default();
|
let mut fn_traits = FxIndexMap::default();
|
||||||
let mut is_sized = false;
|
let mut is_sized = false;
|
||||||
|
|
||||||
for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
|
for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
|
||||||
let predicate = predicate.subst(tcx, substs);
|
|
||||||
let bound_predicate = predicate.kind();
|
let bound_predicate = predicate.kind();
|
||||||
|
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
|
||||||
use crate::ty::visit::{TypeVisitable, TypeVisitor};
|
use crate::ty::visit::{TypeVisitable, TypeVisitor};
|
||||||
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
|
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
|
||||||
|
|
||||||
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::intern::{Interned, WithStableHash};
|
use rustc_data_structures::intern::{Interned, WithStableHash};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
@ -558,6 +559,28 @@ impl<T, U> EarlyBinder<(T, U)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
|
||||||
|
pub fn subst_iter(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
substs: &'s [GenericArg<'tcx>],
|
||||||
|
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
|
||||||
|
self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
|
||||||
|
EarlyBinder<T>
|
||||||
|
{
|
||||||
|
pub fn subst_iter_copied(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
substs: &'s [GenericArg<'tcx>],
|
||||||
|
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
|
||||||
|
self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EarlyBinderIter<T> {
|
pub struct EarlyBinderIter<T> {
|
||||||
t: T,
|
t: T,
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
|
||||||
} else {
|
} else {
|
||||||
("", "if you meant to write a `str` literal, use double quotes")
|
("", "if you meant to write a `str` literal, use double quotes")
|
||||||
};
|
};
|
||||||
|
let mut escaped = String::with_capacity(lit.len());
|
||||||
|
let mut chrs = lit.chars().peekable();
|
||||||
|
while let Some(first) = chrs.next() {
|
||||||
|
match (first, chrs.peek()) {
|
||||||
|
('\\', Some('"')) => {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push('"');
|
||||||
|
chrs.next();
|
||||||
|
}
|
||||||
|
('"', _) => {
|
||||||
|
escaped.push('\\');
|
||||||
|
escaped.push('"')
|
||||||
|
}
|
||||||
|
(c, _) => escaped.push(c),
|
||||||
|
};
|
||||||
|
}
|
||||||
handler.span_suggestion(
|
handler.span_suggestion(
|
||||||
span_with_quotes,
|
span_with_quotes,
|
||||||
msg,
|
msg,
|
||||||
format!("{}\"{}\"", prefix, lit),
|
format!("{prefix}\"{escaped}\""),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -764,6 +764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
|
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut unsatisfied_const = false;
|
||||||
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
|
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
|
||||||
let non_const_predicate = trait_ref.without_const();
|
let non_const_predicate = trait_ref.without_const();
|
||||||
let non_const_obligation = Obligation {
|
let non_const_obligation = Obligation {
|
||||||
|
@ -773,6 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
recursion_depth: obligation.recursion_depth,
|
recursion_depth: obligation.recursion_depth,
|
||||||
};
|
};
|
||||||
if self.predicate_may_hold(&non_const_obligation) {
|
if self.predicate_may_hold(&non_const_obligation) {
|
||||||
|
unsatisfied_const = true;
|
||||||
err.span_note(
|
err.span_note(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -924,7 +926,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !trait_ref.has_non_region_infer()
|
} else if !trait_ref.has_non_region_infer()
|
||||||
&& self.predicate_can_apply(obligation.param_env, trait_ref)
|
&& self.predicate_can_apply(obligation.param_env, trait_predicate)
|
||||||
{
|
{
|
||||||
// If a where-clause may be useful, remind the
|
// If a where-clause may be useful, remind the
|
||||||
// user that they can add it.
|
// user that they can add it.
|
||||||
|
@ -939,7 +941,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
None,
|
None,
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
);
|
);
|
||||||
} else if !suggested {
|
} else if !suggested && !unsatisfied_const {
|
||||||
// Can't show anything else useful, try to find similar impls.
|
// Can't show anything else useful, try to find similar impls.
|
||||||
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
|
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
|
||||||
if !self.report_similar_impl_candidates(
|
if !self.report_similar_impl_candidates(
|
||||||
|
@ -1436,7 +1438,7 @@ trait InferCtxtPrivExt<'tcx> {
|
||||||
fn predicate_can_apply(
|
fn predicate_can_apply(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
pred: ty::PolyTraitRef<'tcx>,
|
pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
|
|
||||||
fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
|
fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
|
||||||
|
@ -2511,7 +2513,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
fn predicate_can_apply(
|
fn predicate_can_apply(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
pred: ty::PolyTraitRef<'tcx>,
|
pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
struct ParamToVarFolder<'a, 'tcx> {
|
struct ParamToVarFolder<'a, 'tcx> {
|
||||||
infcx: &'a InferCtxt<'tcx>,
|
infcx: &'a InferCtxt<'tcx>,
|
||||||
|
@ -2555,7 +2557,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
let obligation = Obligation::new(
|
let obligation = Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
param_env,
|
param_env,
|
||||||
cleaned_pred.without_const().to_predicate(selcx.tcx()),
|
cleaned_pred.to_predicate(selcx.tcx()),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.predicate_may_hold(&obligation)
|
self.predicate_may_hold(&obligation)
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized;
|
||||||
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
|
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
@ -253,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
let result = tcx.normalize_projection_ty(c_data)?;
|
let result = tcx.normalize_projection_ty(c_data)?;
|
||||||
// We don't expect ambiguity.
|
// We don't expect ambiguity.
|
||||||
if result.is_ambiguous() {
|
if result.is_ambiguous() {
|
||||||
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
|
// Rustdoc normalizes possibly not well-formed types, so only
|
||||||
|
// treat this as a bug if we're not in rustdoc.
|
||||||
|
if !tcx.sess.opts.actually_rustdoc {
|
||||||
|
tcx.sess.delay_span_bug(
|
||||||
|
DUMMY_SP,
|
||||||
|
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
let InferOk { value: result, obligations } =
|
let InferOk { value: result, obligations } =
|
||||||
self.infcx.instantiate_query_response_and_region_obligations(
|
self.infcx.instantiate_query_response_and_region_obligations(
|
||||||
|
@ -296,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
let result = tcx.normalize_projection_ty(c_data)?;
|
let result = tcx.normalize_projection_ty(c_data)?;
|
||||||
// We don't expect ambiguity.
|
// We don't expect ambiguity.
|
||||||
if result.is_ambiguous() {
|
if result.is_ambiguous() {
|
||||||
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
|
// Rustdoc normalizes possibly not well-formed types, so only
|
||||||
|
// treat this as a bug if we're not in rustdoc.
|
||||||
|
if !tcx.sess.opts.actually_rustdoc {
|
||||||
|
tcx.sess.delay_span_bug(
|
||||||
|
DUMMY_SP,
|
||||||
|
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
let InferOk { value: result, obligations } =
|
let InferOk { value: result, obligations } =
|
||||||
self.infcx.instantiate_query_response_and_region_obligations(
|
self.infcx.instantiate_query_response_and_region_obligations(
|
||||||
|
|
|
@ -1851,7 +1851,7 @@ impl String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes and leaks the `String`, returning a mutable reference to the contents,
|
/// Consumes and leaks the `String`, returning a mutable reference to the contents,
|
||||||
/// `&'a mut str`.
|
/// `&'static mut str`.
|
||||||
///
|
///
|
||||||
/// This is mainly useful for data that lives for the remainder of
|
/// This is mainly useful for data that lives for the remainder of
|
||||||
/// the program's life. Dropping the returned reference will cause a memory
|
/// the program's life. Dropping the returned reference will cause a memory
|
||||||
|
|
|
@ -920,7 +920,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-results .result-name, .search-results div.desc, .search-results .result-description {
|
.search-results .result-name, .search-results div.desc {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
.search-results .result-name {
|
.search-results .result-name {
|
||||||
|
@ -1899,10 +1899,10 @@ in storage.js
|
||||||
border-bottom: 1px solid #aaa9;
|
border-bottom: 1px solid #aaa9;
|
||||||
padding: 5px 0px;
|
padding: 5px 0px;
|
||||||
}
|
}
|
||||||
.search-results .result-name, .search-results div.desc, .search-results .result-description {
|
.search-results .result-name, .search-results div.desc {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.search-results div.desc, .search-results .result-description, .item-right {
|
.search-results div.desc, .item-right {
|
||||||
padding-left: 2em;
|
padding-left: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,109 +150,85 @@ assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
|
||||||
assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "20px"})
|
assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "20px"})
|
||||||
assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
|
assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
|
||||||
|
|
||||||
// Checking colors now.
|
// Needed to check colors
|
||||||
show-text: true
|
show-text: true
|
||||||
local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
|
|
||||||
goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
|
goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h2",
|
define-function: (
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
|
"check-colors",
|
||||||
|
(theme, heading_color, small_heading_color, heading_border_color),
|
||||||
|
[
|
||||||
|
("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
|
||||||
|
("reload"),
|
||||||
|
("assert-css", (
|
||||||
|
".top-doc .docblock h2",
|
||||||
|
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
".top-doc .docblock h3",
|
||||||
|
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
".top-doc .docblock h4",
|
||||||
|
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
".top-doc .docblock h5",
|
||||||
|
{"color": |small_heading_color|, "border-bottom-width": "0px"},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
"#implementations-list .docblock h4",
|
||||||
|
{"color": |heading_color|, "border-bottom-width": "0px"},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
"#implementations-list .docblock h5",
|
||||||
|
{"color": |small_heading_color|, "border-bottom-width": "0px"},
|
||||||
|
)),
|
||||||
|
("assert-css", (
|
||||||
|
"#implementations-list .docblock h6",
|
||||||
|
{"color": |small_heading_color|, "border-bottom-width": "0px"},
|
||||||
|
)),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
assert-css: (
|
call-function: (
|
||||||
".top-doc .docblock h3",
|
"check-colors",
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
|
{
|
||||||
|
"theme": "ayu",
|
||||||
|
"heading_color": "rgb(255, 255, 255)",
|
||||||
|
"small_heading_color": "rgb(197, 197, 197)",
|
||||||
|
"heading_border_color": "rgb(92, 103, 115)",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
assert-css: (
|
call-function: (
|
||||||
".top-doc .docblock h4",
|
"check-colors",
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
|
{
|
||||||
|
"theme": "dark",
|
||||||
|
"heading_color": "rgb(221, 221, 221)",
|
||||||
|
"small_heading_color": "rgb(221, 221, 221)",
|
||||||
|
"heading_border_color": "rgb(210, 210, 210)",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
assert-css: (
|
call-function: (
|
||||||
".top-doc .docblock h5",
|
"check-colors",
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
|
{
|
||||||
)
|
"theme": "light",
|
||||||
assert-css: (
|
"heading_color": "rgb(0, 0, 0)",
|
||||||
"#implementations-list .docblock h4",
|
"small_heading_color": "rgb(0, 0, 0)",
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
|
"heading_border_color": "rgb(221, 221, 221)",
|
||||||
)
|
},
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h5",
|
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h6",
|
|
||||||
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
local-storage: {"rustdoc-theme": "dark"}
|
define-function: (
|
||||||
reload:
|
"check-since-color",
|
||||||
assert-css: (
|
(theme),
|
||||||
".top-doc .docblock h2",
|
[
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
|
("local-storage", {"rustdoc-theme": |theme|}),
|
||||||
)
|
("reload"),
|
||||||
assert-css: (
|
("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)),
|
||||||
".top-doc .docblock h3",
|
],
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h4",
|
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h5",
|
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h4",
|
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h5",
|
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h6",
|
|
||||||
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
local-storage: {"rustdoc-theme": "ayu"}
|
|
||||||
reload:
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h2",
|
|
||||||
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h2",
|
|
||||||
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h4",
|
|
||||||
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
".top-doc .docblock h5",
|
|
||||||
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h4",
|
|
||||||
{"color": "rgb(255, 255, 255)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h5",
|
|
||||||
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
assert-css: (
|
|
||||||
"#implementations-list .docblock h6",
|
|
||||||
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
|
|
||||||
)
|
|
||||||
|
|
||||||
local-storage: {"rustdoc-theme": "light"}
|
|
||||||
goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
|
goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
|
||||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
call-function: ("check-since-color", ("ayu"))
|
||||||
|
call-function: ("check-since-color", ("dark"))
|
||||||
local-storage: {"rustdoc-theme": "dark"}
|
call-function: ("check-since-color", ("light"))
|
||||||
reload:
|
|
||||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
|
||||||
|
|
||||||
local-storage: {"rustdoc-theme": "ayu"}
|
|
||||||
reload:
|
|
||||||
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
|
|
||||||
|
|
24
src/test/rustdoc/not-wf-ambiguous-normalization.rs
Normal file
24
src/test/rustdoc/not-wf-ambiguous-normalization.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// compile-flags: -Znormalize-docs
|
||||||
|
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Allocator {
|
||||||
|
type Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DefaultAllocator;
|
||||||
|
|
||||||
|
// This unconstrained impl parameter causes the normalization of
|
||||||
|
// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
|
||||||
|
// which caused an ICE with `-Znormalize-docs`.
|
||||||
|
impl<T> Allocator for DefaultAllocator {
|
||||||
|
type Buffer = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
|
||||||
|
|
||||||
|
fn foo() -> A {
|
||||||
|
|_| ()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -10,16 +10,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
|
||||||
|
|
|
|
||||||
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
||||||
| ^^
|
| ^^
|
||||||
= help: the following other types implement trait `PartialEq<Rhs>`:
|
|
||||||
f32
|
|
||||||
f64
|
|
||||||
i128
|
|
||||||
i16
|
|
||||||
i32
|
|
||||||
i64
|
|
||||||
i8
|
|
||||||
isize
|
|
||||||
and 6 others
|
|
||||||
|
|
||||||
error[E0277]: can't compare `*const i32` with `_` in const contexts
|
error[E0277]: can't compare `*const i32` with `_` in const contexts
|
||||||
--> $DIR/const_raw_ptr_ops.rs:6:44
|
--> $DIR/const_raw_ptr_ops.rs:6:44
|
||||||
|
@ -33,16 +23,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
|
||||||
|
|
|
|
||||||
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||||
| ^^
|
| ^^
|
||||||
= help: the following other types implement trait `PartialEq<Rhs>`:
|
|
||||||
f32
|
|
||||||
f64
|
|
||||||
i128
|
|
||||||
i16
|
|
||||||
i32
|
|
||||||
i64
|
|
||||||
i8
|
|
||||||
isize
|
|
||||||
and 6 others
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,6 @@ note: the trait `PartialOrd` is implemented for `*const ()`, but that implementa
|
||||||
|
|
|
|
||||||
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
||||||
| ^
|
| ^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | fn main() where *const (): ~const PartialOrd {
|
|
||||||
| ++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,6 @@ note: the trait `IndexMut<usize>` is implemented for `Vec<usize>`, but that impl
|
||||||
|
|
|
|
||||||
LL | self.bar[0] = baz.len();
|
LL | self.bar[0] = baz.len();
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | impl<'a> Foo<'a> where Vec<usize>: ~const IndexMut<usize> {
|
|
||||||
| ++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
13
src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
Normal file
13
src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
|
pub trait Foo {
|
||||||
|
async fn woopsie_async(&self) -> String {
|
||||||
|
42
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/default-body-type-err-2.rs:8:9
|
||||||
|
|
|
||||||
|
LL | 42
|
||||||
|
| ^^- help: try using a conversion method: `.to_string()`
|
||||||
|
| |
|
||||||
|
| expected struct `String`, found integer
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
13
src/test/ui/impl-trait/in-trait/default-body-type-err.rs
Normal file
13
src/test/ui/impl-trait/in-trait/default-body-type-err.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(return_position_impl_trait_in_trait)]
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
pub trait Foo {
|
||||||
|
fn lol(&self) -> impl Deref<Target = String> {
|
||||||
|
//~^ type mismatch resolving `<&i32 as Deref>::Target == String`
|
||||||
|
&1i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
Normal file
12
src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
|
||||||
|
--> $DIR/default-body-type-err.rs:7:22
|
||||||
|
|
|
||||||
|
LL | fn lol(&self) -> impl Deref<Target = String> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
|
||||||
|
LL |
|
||||||
|
LL | &1i32
|
||||||
|
| ----- return type was inferred to be `&i32` here
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0271`.
|
|
@ -1,4 +1,4 @@
|
||||||
// known-bug: #102688
|
// check-pass
|
||||||
// edition:2021
|
// edition:2021
|
||||||
|
|
||||||
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
|
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
error[E0720]: cannot resolve opaque type
|
|
||||||
--> $DIR/default-body-with-rpit.rs:10:28
|
|
||||||
|
|
|
||||||
LL | async fn baz(&self) -> impl Debug {
|
|
||||||
| ^^^^^^^^^^ cannot resolve opaque type
|
|
||||||
|
|
|
||||||
= note: these returned values have a concrete "never" type
|
|
||||||
= help: this error will resolve once the item's body returns a concrete type
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0720`.
|
|
85
src/test/ui/impl-trait/issue-103181-1.rs
Normal file
85
src/test/ui/impl-trait/issue-103181-1.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
mod hyper {
|
||||||
|
use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll};
|
||||||
|
|
||||||
|
pub trait HttpBody {
|
||||||
|
type Error;
|
||||||
|
}
|
||||||
|
impl HttpBody for () {
|
||||||
|
//~^ ERROR not all trait items implemented, missing: `Error`
|
||||||
|
// don't implement `Error` here for the ICE
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Server<I, S>(I, S);
|
||||||
|
|
||||||
|
pub fn serve<I, S>(_: S) -> Server<I, S> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, B> Future for Server<(), S>
|
||||||
|
where
|
||||||
|
S: MakeServiceRef<(), (), ResBody = B>,
|
||||||
|
B: HttpBody,
|
||||||
|
B::Error: Debug,
|
||||||
|
{
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MakeServiceRef<Target, ReqBody> {
|
||||||
|
type ResBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> MakeServiceRef<(), ()> for T
|
||||||
|
where
|
||||||
|
T: for<'a> Service<&'a (), Response = S>,
|
||||||
|
S: Service<()>,
|
||||||
|
{
|
||||||
|
type ResBody = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MakeServiceFn<F>(pub F);
|
||||||
|
pub struct ServiceFn<F, R>(pub PhantomData<(F, R)>);
|
||||||
|
|
||||||
|
pub trait Service<Request> {
|
||||||
|
type Response;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> Ret,
|
||||||
|
Ret: Future<Output = Result<Svc, ()>>,
|
||||||
|
{
|
||||||
|
type Response = Svc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, ReqBody, Ret, ResBody, E> Service<ReqBody> for ServiceFn<F, ReqBody>
|
||||||
|
where
|
||||||
|
F: Fn() -> Ret,
|
||||||
|
Ret: Future<Output = Result<ResBody, E>>,
|
||||||
|
{
|
||||||
|
type Response = ResBody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn smarvice() -> Result<(), ()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn service_fn<F, R, S>(f: F) -> hyper::ServiceFn<F, R>
|
||||||
|
where
|
||||||
|
F: Fn() -> S,
|
||||||
|
{
|
||||||
|
hyper::ServiceFn(std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn iceice() {
|
||||||
|
let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) });
|
||||||
|
hyper::serve::<(), _>(service).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/impl-trait/issue-103181-1.stderr
Normal file
12
src/test/ui/impl-trait/issue-103181-1.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0046]: not all trait items implemented, missing: `Error`
|
||||||
|
--> $DIR/issue-103181-1.rs:9:5
|
||||||
|
|
|
||||||
|
LL | type Error;
|
||||||
|
| ---------- `Error` from trait
|
||||||
|
LL | }
|
||||||
|
LL | impl HttpBody for () {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0046`.
|
29
src/test/ui/impl-trait/issue-103181-2.rs
Normal file
29
src/test/ui/impl-trait/issue-103181-2.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
trait SendFuture: Send {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Fut: Send> SendFuture for Fut {
|
||||||
|
type Output = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn broken_fut() {
|
||||||
|
ident_error;
|
||||||
|
//~^ ERROR cannot find value `ident_error` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
// triggers normalization of `<Fut as SendFuture>::Output`,
|
||||||
|
// which requires `Fut: Send`.
|
||||||
|
fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}
|
||||||
|
|
||||||
|
async fn iceice<A, B>()
|
||||||
|
// <- async fn is necessary
|
||||||
|
where
|
||||||
|
A: Send,
|
||||||
|
B: Send, // <- a second bound
|
||||||
|
{
|
||||||
|
normalize(broken_fut(), ());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
9
src/test/ui/impl-trait/issue-103181-2.stderr
Normal file
9
src/test/ui/impl-trait/issue-103181-2.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0425]: cannot find value `ident_error` in this scope
|
||||||
|
--> $DIR/issue-103181-2.rs:12:5
|
||||||
|
|
|
||||||
|
LL | ident_error;
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0425`.
|
|
@ -8,4 +8,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: char = 'a'; //~ ERROR mismatched types
|
let _: char = 'a'; //~ ERROR mismatched types
|
||||||
let _: char = '人'; //~ ERROR mismatched types
|
let _: char = '人'; //~ ERROR mismatched types
|
||||||
|
let _: char = '\''; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: char = "a"; //~ ERROR mismatched types
|
let _: char = "a"; //~ ERROR mismatched types
|
||||||
let _: char = "人"; //~ ERROR mismatched types
|
let _: char = "人"; //~ ERROR mismatched types
|
||||||
|
let _: char = "'"; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
|
||||||
LL | let _: char = '人';
|
LL | let _: char = '人';
|
||||||
| ~~~~
|
| ~~~~
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/char-as-str-single.rs:11:19
|
||||||
|
|
|
||||||
|
LL | let _: char = "'";
|
||||||
|
| ---- ^^^ expected `char`, found `&str`
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
help: if you meant to write a `char` literal, use single quotes
|
||||||
|
|
|
||||||
|
LL | let _: char = '\'';
|
||||||
|
| ~~~~
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -4,5 +4,7 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: &str = "a"; //~ ERROR mismatched types
|
let _: &str = "a"; //~ ERROR mismatched types
|
||||||
|
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
|
||||||
|
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,7 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: &str = 'a'; //~ ERROR mismatched types
|
let _: &str = 'a'; //~ ERROR mismatched types
|
||||||
|
let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
|
||||||
|
let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
|
error: character literal may only contain one codepoint
|
||||||
|
--> $DIR/str-as-char.rs:8:19
|
||||||
|
|
|
||||||
|
LL | let _: &str = '"""';
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
help: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
|
||||||
|
LL | let _: &str = "\"\"\"";
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
error: character literal may only contain one codepoint
|
||||||
|
--> $DIR/str-as-char.rs:9:19
|
||||||
|
|
|
||||||
|
LL | let _: &str = '\"\"\"';
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
help: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
|
||||||
|
LL | let _: &str = "\"\"\"";
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/str-as-char.rs:7:19
|
--> $DIR/str-as-char.rs:7:19
|
||||||
|
|
|
|
||||||
|
@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
|
||||||
LL | let _: &str = "a";
|
LL | let _: &str = "a";
|
||||||
| ~~~
|
| ~~~
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -15,10 +15,6 @@ note: required by a bound in `Foo::Bar`
|
||||||
|
|
|
|
||||||
LL | type Bar: ~const std::ops::Add;
|
LL | type Bar: ~const std::ops::Add;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
|
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add {
|
|
||||||
| +++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ note: the trait `Plus` is implemented for `u32`, but that implementation is not
|
||||||
|
|
|
|
||||||
LL | a.plus(b)
|
LL | a.plus(b)
|
||||||
| ^^^^
|
| ^^^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: ~const Plus {
|
|
||||||
| ++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ note: the trait `PartialEq<_>` is implemented for `T`, but that implementation i
|
||||||
|
|
|
|
||||||
LL | *t == *t
|
LL | *t == *t
|
||||||
| ^^
|
| ^^
|
||||||
= help: the trait `PartialEq<&B>` is implemented for `&A`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,6 @@ note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that imp
|
||||||
|
|
|
|
||||||
LL | NonConstImpl.a();
|
LL | NonConstImpl.a();
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
|
|
||||||
| +++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
|
||||||
|
|
|
|
||||||
LL | NonConst.func();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
|
|
||||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
|
||||||
|
|
|
|
||||||
LL | NonConst.func();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
|
|
||||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,6 @@ note: required by a bound in `foo`
|
||||||
|
|
|
|
||||||
LL | const fn foo<T>() where T: ~const Tr {}
|
LL | const fn foo<T>() where T: ~const Tr {}
|
||||||
| ^^^^^^^^^ required by this bound in `foo`
|
| ^^^^^^^^^ required by this bound in `foo`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | pub trait Foo where (): ~const Tr {
|
|
||||||
| +++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,6 @@ note: the trait `Tr` is implemented for `()`, but that implementation is not `co
|
||||||
|
|
|
|
||||||
LL | ().a()
|
LL | ().a()
|
||||||
| ^^
|
| ^^
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | pub trait Tr where (): ~const Tr {
|
|
||||||
| +++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,6 @@ note: required by a bound in `Bar`
|
||||||
|
|
|
|
||||||
LL | trait Bar: ~const Foo {}
|
LL | trait Bar: ~const Foo {}
|
||||||
| ^^^^^^^^^^ required by this bound in `Bar`
|
| ^^^^^^^^^^ required by this bound in `Bar`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | impl const Bar for S where S: ~const Foo {}
|
|
||||||
| +++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -657,21 +657,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
|
||||||
let mut output = None;
|
let mut output = None;
|
||||||
let lang_items = cx.tcx.lang_items();
|
let lang_items = cx.tcx.lang_items();
|
||||||
|
|
||||||
for pred in cx
|
for (pred, _) in cx
|
||||||
.tcx
|
.tcx
|
||||||
.bound_explicit_item_bounds(ty.item_def_id)
|
.bound_explicit_item_bounds(ty.item_def_id)
|
||||||
.transpose_iter()
|
.subst_iter_copied(cx.tcx, ty.substs)
|
||||||
.map(|x| x.map_bound(|(p, _)| p))
|
|
||||||
{
|
{
|
||||||
match pred.0.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
PredicateKind::Trait(p)
|
PredicateKind::Trait(p)
|
||||||
if (lang_items.fn_trait() == Some(p.def_id())
|
if (lang_items.fn_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
|
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
|
||||||
{
|
{
|
||||||
let i = pred
|
let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));
|
||||||
.map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
|
|
||||||
.subst(cx.tcx, ty.substs);
|
|
||||||
|
|
||||||
if inputs.map_or(false, |inputs| inputs != i) {
|
if inputs.map_or(false, |inputs| inputs != i) {
|
||||||
// Multiple different fn trait impls. Is this even allowed?
|
// Multiple different fn trait impls. Is this even allowed?
|
||||||
|
@ -684,10 +681,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
|
||||||
// Multiple different fn trait impls. Is this even allowed?
|
// Multiple different fn trait impls. Is this even allowed?
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
output = Some(
|
output = pred.kind().rebind(p.term.ty()).transpose();
|
||||||
pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
|
|
||||||
.subst(cx.tcx, ty.substs),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue