Auto merge of #121055 - matthiaskrgr:rollup-bzn5sda, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #118882 (Check normalized call signature for WF in mir typeck) - #120999 (rustdoc: replace `clean::InstantiationParam` with `clean::GenericArg`) - #121002 (remove unnecessary calls to `commit_if_ok`) - #121005 (Remove jsha from the rustdoc review rotation) - #121014 (Remove `force_print_diagnostic`) - #121043 (add lcnr to the compiler-team assignment group) - #121046 (Fix incorrect use of `compile_fail`) - #121047 (Do not assemble candidates for default impls) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7508c3e4c1
@ -1432,7 +1432,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (sig, map) = tcx.instantiate_bound_regions(sig, |br| {
|
let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
|
||||||
use crate::renumber::RegionCtxt;
|
use crate::renumber::RegionCtxt;
|
||||||
|
|
||||||
let region_ctxt_fn = || {
|
let region_ctxt_fn = || {
|
||||||
@ -1454,7 +1454,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
region_ctxt_fn,
|
region_ctxt_fn,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
debug!(?sig);
|
debug!(?unnormalized_sig);
|
||||||
// IMPORTANT: We have to prove well formed for the function signature before
|
// IMPORTANT: We have to prove well formed for the function signature before
|
||||||
// we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc`
|
// we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc`
|
||||||
// get normalized away, causing us to ignore the `'b: 'a` bound used by the function.
|
// get normalized away, causing us to ignore the `'b: 'a` bound used by the function.
|
||||||
@ -1464,7 +1464,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
//
|
//
|
||||||
// See #91068 for an example.
|
// See #91068 for an example.
|
||||||
self.prove_predicates(
|
self.prove_predicates(
|
||||||
sig.inputs_and_output.iter().map(|ty| {
|
unnormalized_sig.inputs_and_output.iter().map(|ty| {
|
||||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||||
ty.into(),
|
ty.into(),
|
||||||
)))
|
)))
|
||||||
@ -1472,7 +1472,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
term_location.to_locations(),
|
term_location.to_locations(),
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
);
|
);
|
||||||
let sig = self.normalize(sig, term_location);
|
|
||||||
|
let sig = self.normalize(unnormalized_sig, term_location);
|
||||||
|
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
|
||||||
|
// with built-in `Fn` implementations, since the impl may not be
|
||||||
|
// well-formed itself.
|
||||||
|
if sig != unnormalized_sig {
|
||||||
|
self.prove_predicates(
|
||||||
|
sig.inputs_and_output.iter().map(|ty| {
|
||||||
|
ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||||
|
ty::ClauseKind::WellFormed(ty.into()),
|
||||||
|
))
|
||||||
|
}),
|
||||||
|
term_location.to_locations(),
|
||||||
|
ConstraintCategory::Boring,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.check_call_dest(body, term, &sig, *destination, *target, term_location);
|
self.check_call_dest(body, term, &sig, *destination, *target, term_location);
|
||||||
|
|
||||||
// The ordinary liveness rules will ensure that all
|
// The ordinary liveness rules will ensure that all
|
||||||
|
@ -78,6 +78,7 @@ use std::fmt;
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
use std::ops::DerefMut;
|
||||||
use std::panic;
|
use std::panic;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -666,22 +667,51 @@ impl DiagCtxt {
|
|||||||
/// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
|
/// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
|
||||||
/// the overall count of emitted error diagnostics.
|
/// the overall count of emitted error diagnostics.
|
||||||
pub fn reset_err_count(&self) {
|
pub fn reset_err_count(&self) {
|
||||||
|
// Use destructuring so that if a field gets added to `DiagCtxtInner`, it's impossible to
|
||||||
|
// fail to update this method as well.
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.stashed_err_count = 0;
|
let DiagCtxtInner {
|
||||||
inner.deduplicated_err_count = 0;
|
flags: _,
|
||||||
inner.deduplicated_warn_count = 0;
|
err_guars,
|
||||||
inner.must_produce_diag = false;
|
lint_err_guars,
|
||||||
inner.has_printed = false;
|
delayed_bugs,
|
||||||
inner.suppressed_expected_diag = false;
|
stashed_err_count,
|
||||||
|
deduplicated_err_count,
|
||||||
|
deduplicated_warn_count,
|
||||||
|
emitter: _,
|
||||||
|
must_produce_diag,
|
||||||
|
has_printed,
|
||||||
|
suppressed_expected_diag,
|
||||||
|
taught_diagnostics,
|
||||||
|
emitted_diagnostic_codes,
|
||||||
|
emitted_diagnostics,
|
||||||
|
stashed_diagnostics,
|
||||||
|
future_breakage_diagnostics,
|
||||||
|
check_unstable_expect_diagnostics,
|
||||||
|
unstable_expect_diagnostics,
|
||||||
|
fulfilled_expectations,
|
||||||
|
ice_file: _,
|
||||||
|
} = inner.deref_mut();
|
||||||
|
|
||||||
// actually free the underlying memory (which `clear` would not do)
|
// For the `Vec`s and `HashMap`s, we overwrite with an empty container to free the
|
||||||
inner.err_guars = Default::default();
|
// underlying memory (which `clear` would not do).
|
||||||
inner.lint_err_guars = Default::default();
|
*err_guars = Default::default();
|
||||||
inner.delayed_bugs = Default::default();
|
*lint_err_guars = Default::default();
|
||||||
inner.taught_diagnostics = Default::default();
|
*delayed_bugs = Default::default();
|
||||||
inner.emitted_diagnostic_codes = Default::default();
|
*stashed_err_count = 0;
|
||||||
inner.emitted_diagnostics = Default::default();
|
*deduplicated_err_count = 0;
|
||||||
inner.stashed_diagnostics = Default::default();
|
*deduplicated_warn_count = 0;
|
||||||
|
*must_produce_diag = false;
|
||||||
|
*has_printed = false;
|
||||||
|
*suppressed_expected_diag = false;
|
||||||
|
*taught_diagnostics = Default::default();
|
||||||
|
*emitted_diagnostic_codes = Default::default();
|
||||||
|
*emitted_diagnostics = Default::default();
|
||||||
|
*stashed_diagnostics = Default::default();
|
||||||
|
*future_breakage_diagnostics = Default::default();
|
||||||
|
*check_unstable_expect_diagnostics = false;
|
||||||
|
*unstable_expect_diagnostics = Default::default();
|
||||||
|
*fulfilled_expectations = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
|
/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
|
||||||
@ -780,11 +810,12 @@ impl DiagCtxt {
|
|||||||
match (errors.len(), warnings.len()) {
|
match (errors.len(), warnings.len()) {
|
||||||
(0, 0) => return,
|
(0, 0) => return,
|
||||||
(0, _) => {
|
(0, _) => {
|
||||||
// Use `inner.emitter` directly, otherwise the warning might not be emitted, e.g.
|
// Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a
|
||||||
// with a configuration like `--cap-lints allow --force-warn bare_trait_objects`.
|
// configuration like `--cap-lints allow --force-warn bare_trait_objects`.
|
||||||
inner
|
inner.emit_diagnostic(Diagnostic::new(
|
||||||
.emitter
|
ForceWarning(None),
|
||||||
.emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings)));
|
DiagnosticMessage::Str(warnings),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
(_, 0) => {
|
(_, 0) => {
|
||||||
inner.emit_diagnostic(Diagnostic::new(Error, errors));
|
inner.emit_diagnostic(Diagnostic::new(Error, errors));
|
||||||
@ -812,20 +843,23 @@ impl DiagCtxt {
|
|||||||
error_codes.sort();
|
error_codes.sort();
|
||||||
if error_codes.len() > 1 {
|
if error_codes.len() > 1 {
|
||||||
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
|
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
|
||||||
inner.failure_note(format!(
|
let msg1 = format!(
|
||||||
"Some errors have detailed explanations: {}{}",
|
"Some errors have detailed explanations: {}{}",
|
||||||
error_codes[..limit].join(", "),
|
error_codes[..limit].join(", "),
|
||||||
if error_codes.len() > 9 { "..." } else { "." }
|
if error_codes.len() > 9 { "..." } else { "." }
|
||||||
));
|
);
|
||||||
inner.failure_note(format!(
|
let msg2 = format!(
|
||||||
"For more information about an error, try `rustc --explain {}`.",
|
"For more information about an error, try `rustc --explain {}`.",
|
||||||
&error_codes[0]
|
&error_codes[0]
|
||||||
));
|
);
|
||||||
|
inner.emit_diagnostic(Diagnostic::new(FailureNote, msg1));
|
||||||
|
inner.emit_diagnostic(Diagnostic::new(FailureNote, msg2));
|
||||||
} else {
|
} else {
|
||||||
inner.failure_note(format!(
|
let msg = format!(
|
||||||
"For more information about this error, try `rustc --explain {}`.",
|
"For more information about this error, try `rustc --explain {}`.",
|
||||||
&error_codes[0]
|
&error_codes[0]
|
||||||
));
|
);
|
||||||
|
inner.emit_diagnostic(Diagnostic::new(FailureNote, msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -848,10 +882,6 @@ impl DiagCtxt {
|
|||||||
self.inner.borrow_mut().taught_diagnostics.insert(code)
|
self.inner.borrow_mut().taught_diagnostics.insert(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn force_print_diagnostic(&self, db: Diagnostic) {
|
|
||||||
self.inner.borrow_mut().emitter.emit_diagnostic(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||||
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
||||||
}
|
}
|
||||||
@ -1179,7 +1209,7 @@ impl DiagCtxt {
|
|||||||
span: impl Into<MultiSpan>,
|
span: impl Into<MultiSpan>,
|
||||||
msg: impl Into<DiagnosticMessage>,
|
msg: impl Into<DiagnosticMessage>,
|
||||||
) -> DiagnosticBuilder<'_, ()> {
|
) -> DiagnosticBuilder<'_, ()> {
|
||||||
DiagnosticBuilder::new(self, Note, msg).with_span(span)
|
self.struct_note(msg).with_span(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_lint_diagnostics]
|
#[rustc_lint_diagnostics]
|
||||||
@ -1207,6 +1237,15 @@ impl DiagCtxt {
|
|||||||
DiagnosticBuilder::new(self, Help, msg)
|
DiagnosticBuilder::new(self, Help, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_lint_diagnostics]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn struct_failure_note(
|
||||||
|
&self,
|
||||||
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
) -> DiagnosticBuilder<'_, ()> {
|
||||||
|
DiagnosticBuilder::new(self, FailureNote, msg)
|
||||||
|
}
|
||||||
|
|
||||||
#[rustc_lint_diagnostics]
|
#[rustc_lint_diagnostics]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||||
@ -1406,10 +1445,6 @@ impl DiagCtxtInner {
|
|||||||
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
|
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
|
|
||||||
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush_delayed(&mut self) {
|
fn flush_delayed(&mut self) {
|
||||||
if self.delayed_bugs.is_empty() {
|
if self.delayed_bugs.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -285,13 +285,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
let Trace { at, trace, a_is_expected } = self;
|
let Trace { at, trace, a_is_expected } = self;
|
||||||
at.infcx.commit_if_ok(|_| {
|
|
||||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
||||||
fields
|
fields
|
||||||
.sub(a_is_expected)
|
.sub(a_is_expected)
|
||||||
.relate(a, b)
|
.relate(a, b)
|
||||||
.map(move |_| InferOk { value: (), obligations: fields.obligations })
|
.map(move |_| InferOk { value: (), obligations: fields.obligations })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes `a == b`; the expectation is set by the call to
|
/// Makes `a == b`; the expectation is set by the call to
|
||||||
@ -302,13 +300,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
let Trace { at, trace, a_is_expected } = self;
|
let Trace { at, trace, a_is_expected } = self;
|
||||||
at.infcx.commit_if_ok(|_| {
|
|
||||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
||||||
fields
|
fields
|
||||||
.equate(a_is_expected)
|
.equate(a_is_expected)
|
||||||
.relate(a, b)
|
.relate(a, b)
|
||||||
.map(move |_| InferOk { value: (), obligations: fields.obligations })
|
.map(move |_| InferOk { value: (), obligations: fields.obligations })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
@ -317,13 +313,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
let Trace { at, trace, a_is_expected } = self;
|
let Trace { at, trace, a_is_expected } = self;
|
||||||
at.infcx.commit_if_ok(|_| {
|
|
||||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
||||||
fields
|
fields
|
||||||
.lub(a_is_expected)
|
.lub(a_is_expected)
|
||||||
.relate(a, b)
|
.relate(a, b)
|
||||||
.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
@ -332,13 +326,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
let Trace { at, trace, a_is_expected } = self;
|
let Trace { at, trace, a_is_expected } = self;
|
||||||
at.infcx.commit_if_ok(|_| {
|
|
||||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
|
||||||
fields
|
fields
|
||||||
.glb(a_is_expected)
|
.glb(a_is_expected)
|
||||||
.relate(a, b)
|
.relate(a, b)
|
||||||
.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,7 +620,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
variables1: &OriginalQueryValues<'tcx>,
|
variables1: &OriginalQueryValues<'tcx>,
|
||||||
variables2: impl Fn(BoundVar) -> GenericArg<'tcx>,
|
variables2: impl Fn(BoundVar) -> GenericArg<'tcx>,
|
||||||
) -> InferResult<'tcx, ()> {
|
) -> InferResult<'tcx, ()> {
|
||||||
self.commit_if_ok(|_| {
|
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
for (index, value1) in variables1.var_values.iter().enumerate() {
|
for (index, value1) in variables1.var_values.iter().enumerate() {
|
||||||
let value2 = variables2(BoundVar::new(index));
|
let value2 = variables2(BoundVar::new(index));
|
||||||
@ -655,7 +654,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(InferOk { value: (), obligations })
|
Ok(InferOk { value: (), obligations })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::query::plumbing::CycleError;
|
|||||||
use crate::query::DepKind;
|
use crate::query::DepKind;
|
||||||
use crate::query::{QueryContext, QueryStackFrame};
|
use crate::query::{QueryContext, QueryStackFrame};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{DiagCtxt, Diagnostic, DiagnosticBuilder, Level};
|
use rustc_errors::{DiagCtxt, DiagnosticBuilder};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -628,15 +628,15 @@ pub fn print_query_stack<Qcx: QueryContext>(
|
|||||||
};
|
};
|
||||||
if Some(count_printed) < num_frames || num_frames.is_none() {
|
if Some(count_printed) < num_frames || num_frames.is_none() {
|
||||||
// Only print to stderr as many stack frames as `num_frames` when present.
|
// Only print to stderr as many stack frames as `num_frames` when present.
|
||||||
let mut diag = Diagnostic::new(
|
// FIXME: needs translation
|
||||||
Level::FailureNote,
|
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||||
format!(
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
|
dcx.struct_failure_note(format!(
|
||||||
"#{} [{:?}] {}",
|
"#{} [{:?}] {}",
|
||||||
count_printed, query_info.query.dep_kind, query_info.query.description
|
count_printed, query_info.query.dep_kind, query_info.query.description
|
||||||
),
|
))
|
||||||
);
|
.with_span(query_info.job.span)
|
||||||
diag.span = query_info.job.span.into();
|
.emit();
|
||||||
dcx.force_print_diagnostic(diag);
|
|
||||||
count_printed += 1;
|
count_printed += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +337,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
let mut consider_impls_for_simplified_type = |simp| {
|
let mut consider_impls_for_simplified_type = |simp| {
|
||||||
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
|
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
|
||||||
for &impl_def_id in impls_for_type {
|
for &impl_def_id in impls_for_type {
|
||||||
|
// For every `default impl`, there's always a non-default `impl`
|
||||||
|
// that will *also* apply. There's no reason to register a candidate
|
||||||
|
// for this impl, since it is *not* proof that the trait goal holds.
|
||||||
|
if tcx.defaultness(impl_def_id).is_default() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
||||||
Ok(candidate) => candidates.push(candidate),
|
Ok(candidate) => candidates.push(candidate),
|
||||||
Err(NoSolution) => (),
|
Err(NoSolution) => (),
|
||||||
@ -440,6 +447,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
|
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
|
||||||
for &impl_def_id in trait_impls.blanket_impls() {
|
for &impl_def_id in trait_impls.blanket_impls() {
|
||||||
|
// For every `default impl`, there's always a non-default `impl`
|
||||||
|
// that will *also* apply. There's no reason to register a candidate
|
||||||
|
// for this impl, since it is *not* proof that the trait goal holds.
|
||||||
|
if tcx.defaultness(impl_def_id).is_default() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
||||||
Ok(candidate) => candidates.push(candidate),
|
Ok(candidate) => candidates.push(candidate),
|
||||||
Err(NoSolution) => (),
|
Err(NoSolution) => (),
|
||||||
|
@ -566,6 +566,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For every `default impl`, there's always a non-default `impl`
|
||||||
|
// that will *also* apply. There's no reason to register a candidate
|
||||||
|
// for this impl, since it is *not* proof that the trait goal holds.
|
||||||
|
if self.tcx().defaultness(impl_def_id).is_default() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if self.reject_fn_ptr_impls(
|
if self.reject_fn_ptr_impls(
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
obligation,
|
obligation,
|
||||||
|
@ -192,13 +192,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
&mut obligations,
|
&mut obligations,
|
||||||
);
|
);
|
||||||
|
|
||||||
obligations.extend(self.infcx.commit_if_ok(|_| {
|
obligations.extend(
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
|
.sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
|
||||||
.map(|InferOk { obligations, .. }| obligations)
|
.map(|InferOk { obligations, .. }| obligations)
|
||||||
.map_err(|_| Unimplemented)
|
.map_err(|_| Unimplemented)?,
|
||||||
})?);
|
);
|
||||||
|
|
||||||
// FIXME(compiler-errors): I don't think this is needed.
|
// FIXME(compiler-errors): I don't think this is needed.
|
||||||
if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() {
|
if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() {
|
||||||
@ -532,13 +532,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
&mut nested,
|
&mut nested,
|
||||||
);
|
);
|
||||||
|
|
||||||
nested.extend(self.infcx.commit_if_ok(|_| {
|
nested.extend(
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
|
.sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
|
||||||
.map(|InferOk { obligations, .. }| obligations)
|
.map(|InferOk { obligations, .. }| obligations)
|
||||||
.map_err(|_| Unimplemented)
|
.map_err(|_| Unimplemented)?,
|
||||||
})?);
|
);
|
||||||
|
|
||||||
// Check supertraits hold. This is so that their associated type bounds
|
// Check supertraits hold. This is so that their associated type bounds
|
||||||
// will be checked in the code below.
|
// will be checked in the code below.
|
||||||
|
@ -171,7 +171,7 @@ pub struct Child {
|
|||||||
/// The handle for writing to the child's standard input (stdin), if it
|
/// The handle for writing to the child's standard input (stdin), if it
|
||||||
/// has been captured. You might find it helpful to do
|
/// has been captured. You might find it helpful to do
|
||||||
///
|
///
|
||||||
/// ```compile_fail,E0425
|
/// ```ignore (incomplete)
|
||||||
/// let stdin = child.stdin.take().unwrap();
|
/// let stdin = child.stdin.take().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -183,7 +183,7 @@ pub struct Child {
|
|||||||
/// The handle for reading from the child's standard output (stdout), if it
|
/// The handle for reading from the child's standard output (stdout), if it
|
||||||
/// has been captured. You might find it helpful to do
|
/// has been captured. You might find it helpful to do
|
||||||
///
|
///
|
||||||
/// ```compile_fail,E0425
|
/// ```ignore (incomplete)
|
||||||
/// let stdout = child.stdout.take().unwrap();
|
/// let stdout = child.stdout.take().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -195,7 +195,7 @@ pub struct Child {
|
|||||||
/// The handle for reading from the child's standard error (stderr), if it
|
/// The handle for reading from the child's standard error (stderr), if it
|
||||||
/// has been captured. You might find it helpful to do
|
/// has been captured. You might find it helpful to do
|
||||||
///
|
///
|
||||||
/// ```compile_fail,E0425
|
/// ```ignore (incomplete)
|
||||||
/// let stderr = child.stderr.take().unwrap();
|
/// let stderr = child.stderr.take().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -254,16 +254,14 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
||||||
let def = cx.tcx.named_bound_var(lifetime.hir_id);
|
|
||||||
if let Some(
|
if let Some(
|
||||||
rbv::ResolvedArg::EarlyBound(node_id)
|
rbv::ResolvedArg::EarlyBound(did)
|
||||||
| rbv::ResolvedArg::LateBound(_, _, node_id)
|
| rbv::ResolvedArg::LateBound(_, _, did)
|
||||||
| rbv::ResolvedArg::Free(_, node_id),
|
| rbv::ResolvedArg::Free(_, did),
|
||||||
) = def
|
) = cx.tcx.named_bound_var(lifetime.hir_id)
|
||||||
|
&& let Some(lt) = cx.args.get(&did).and_then(|arg| arg.as_lt())
|
||||||
{
|
{
|
||||||
if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() {
|
return lt.clone();
|
||||||
return lt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Lifetime(lifetime.ident.name)
|
Lifetime(lifetime.ident.name)
|
||||||
}
|
}
|
||||||
@ -1791,12 +1789,12 @@ fn maybe_expand_private_type_alias<'tcx>(
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
if let Some(lt) = lifetime {
|
if let Some(lt) = lifetime {
|
||||||
let cleaned = if !lt.is_anonymous() {
|
let lt = if !lt.is_anonymous() {
|
||||||
clean_lifetime(lt, cx)
|
clean_lifetime(lt, cx)
|
||||||
} else {
|
} else {
|
||||||
Lifetime::elided()
|
Lifetime::elided()
|
||||||
};
|
};
|
||||||
args.insert(param.def_id.to_def_id(), InstantiationParam::Lifetime(cleaned));
|
args.insert(param.def_id.to_def_id(), GenericArg::Lifetime(lt));
|
||||||
}
|
}
|
||||||
indices.lifetimes += 1;
|
indices.lifetimes += 1;
|
||||||
}
|
}
|
||||||
@ -1805,44 +1803,20 @@ fn maybe_expand_private_type_alias<'tcx>(
|
|||||||
let type_ = generic_args.args.iter().find_map(|arg| match arg {
|
let type_ = generic_args.args.iter().find_map(|arg| match arg {
|
||||||
hir::GenericArg::Type(ty) => {
|
hir::GenericArg::Type(ty) => {
|
||||||
if indices.types == j {
|
if indices.types == j {
|
||||||
return Some(ty);
|
return Some(*ty);
|
||||||
}
|
}
|
||||||
j += 1;
|
j += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
if let Some(ty) = type_ {
|
if let Some(ty) = type_.or(*default) {
|
||||||
args.insert(
|
args.insert(param.def_id.to_def_id(), GenericArg::Type(clean_ty(ty, cx)));
|
||||||
param.def_id.to_def_id(),
|
|
||||||
InstantiationParam::Type(clean_ty(ty, cx)),
|
|
||||||
);
|
|
||||||
} else if let Some(default) = *default {
|
|
||||||
args.insert(
|
|
||||||
param.def_id.to_def_id(),
|
|
||||||
InstantiationParam::Type(clean_ty(default, cx)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
indices.types += 1;
|
indices.types += 1;
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Const { .. } => {
|
// FIXME(#82852): Instantiate const parameters.
|
||||||
let mut j = 0;
|
hir::GenericParamKind::Const { .. } => {}
|
||||||
let const_ = generic_args.args.iter().find_map(|arg| match arg {
|
|
||||||
hir::GenericArg::Const(ct) => {
|
|
||||||
if indices.consts == j {
|
|
||||||
return Some(ct);
|
|
||||||
}
|
|
||||||
j += 1;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
if let Some(_) = const_ {
|
|
||||||
args.insert(param.def_id.to_def_id(), InstantiationParam::Constant);
|
|
||||||
}
|
|
||||||
// FIXME(const_generics_defaults)
|
|
||||||
indices.consts += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2228,6 +2228,16 @@ pub(crate) enum GenericArg {
|
|||||||
Infer,
|
Infer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GenericArg {
|
||||||
|
pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
|
||||||
|
if let Self::Lifetime(lt) = self { Some(lt) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_ty(&self) -> Option<&Type> {
|
||||||
|
if let Self::Type(ty) = self { Some(ty) } else { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub(crate) enum GenericArgs {
|
pub(crate) enum GenericArgs {
|
||||||
AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
|
AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
|
||||||
@ -2530,35 +2540,6 @@ pub(crate) enum TypeBindingKind {
|
|||||||
Constraint { bounds: Vec<GenericBound> },
|
Constraint { bounds: Vec<GenericBound> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type, lifetime, or constant that a private type alias's parameter should be
|
|
||||||
/// replaced with when expanding a use of that type alias.
|
|
||||||
///
|
|
||||||
/// For example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// type PrivAlias<T> = Vec<T>;
|
|
||||||
///
|
|
||||||
/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
|
|
||||||
/// [`InstantiationParam`] is used to record that `T` should be mapped to `i32`.
|
|
||||||
pub(crate) enum InstantiationParam {
|
|
||||||
Type(Type),
|
|
||||||
Lifetime(Lifetime),
|
|
||||||
Constant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InstantiationParam {
|
|
||||||
pub(crate) fn as_ty(&self) -> Option<&Type> {
|
|
||||||
if let Self::Type(ty) = self { Some(ty) } else { None }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
|
|
||||||
if let Self::Lifetime(lt) = self { Some(lt) } else { None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
|
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
mod size_asserts {
|
mod size_asserts {
|
||||||
|
@ -44,10 +44,13 @@ pub(crate) struct DocContext<'tcx> {
|
|||||||
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
|
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
|
||||||
/// the same time.
|
/// the same time.
|
||||||
pub(crate) active_extern_traits: DefIdSet,
|
pub(crate) active_extern_traits: DefIdSet,
|
||||||
// The current set of parameter instantiations,
|
/// The current set of parameter instantiations for expanding type aliases at the HIR level.
|
||||||
// for expanding type aliases at the HIR level:
|
///
|
||||||
/// Table `DefId` of type, lifetime, or const parameter -> instantiated type, lifetime, or const
|
/// Maps from the `DefId` of a lifetime or type parameter to the
|
||||||
pub(crate) args: DefIdMap<clean::InstantiationParam>,
|
/// generic argument it's currently instantiated to in this context.
|
||||||
|
// FIXME(#82852): We don't record const params since we don't visit const exprs at all and
|
||||||
|
// therefore wouldn't use the corresp. generic arg anyway. Add support for them.
|
||||||
|
pub(crate) args: DefIdMap<clean::GenericArg>,
|
||||||
pub(crate) current_type_aliases: DefIdMap<usize>,
|
pub(crate) current_type_aliases: DefIdMap<usize>,
|
||||||
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
|
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
|
||||||
pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
|
pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
|
||||||
@ -87,7 +90,7 @@ impl<'tcx> DocContext<'tcx> {
|
|||||||
/// the generic parameters for a type alias' RHS.
|
/// the generic parameters for a type alias' RHS.
|
||||||
pub(crate) fn enter_alias<F, R>(
|
pub(crate) fn enter_alias<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
args: DefIdMap<clean::InstantiationParam>,
|
args: DefIdMap<clean::GenericArg>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
f: F,
|
f: F,
|
||||||
) -> R
|
) -> R
|
||||||
|
@ -9,8 +9,8 @@ LL | |
|
|||||||
LL | | });
|
LL | | });
|
||||||
| |______^ expected due to this
|
| |______^ expected due to this
|
||||||
|
|
|
|
||||||
= note: expected closure signature `fn(_, _) -> _`
|
= note: expected closure signature `fn(_, u32) -> _`
|
||||||
found closure signature `fn(u32, i32) -> _`
|
found closure signature `fn(_, i32) -> _`
|
||||||
note: required by a bound in `with_closure`
|
note: required by a bound in `with_closure`
|
||||||
--> $DIR/expect-infer-var-appearing-twice.rs:2:14
|
--> $DIR/expect-infer-var-appearing-twice.rs:2:14
|
||||||
|
|
|
|
||||||
|
27
tests/ui/nll/check-normalized-sig-for-wf.rs
Normal file
27
tests/ui/nll/check-normalized-sig-for-wf.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// <https://github.com/rust-lang/rust/issues/114936>
|
||||||
|
fn whoops(
|
||||||
|
s: String,
|
||||||
|
f: impl for<'s> FnOnce(&'s str) -> (&'static str, [&'static &'s (); 0]),
|
||||||
|
) -> &'static str
|
||||||
|
{
|
||||||
|
f(&s).0
|
||||||
|
//~^ ERROR `s` does not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
// <https://github.com/rust-lang/rust/issues/118876>
|
||||||
|
fn extend<T>(input: &T) -> &'static T {
|
||||||
|
struct Bounded<'a, 'b: 'static, T>(&'a T, [&'b (); 0]);
|
||||||
|
let n: Box<dyn FnOnce(&T) -> Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, []));
|
||||||
|
n(input).0
|
||||||
|
//~^ ERROR borrowed data escapes outside of function
|
||||||
|
}
|
||||||
|
|
||||||
|
// <https://github.com/rust-lang/rust/issues/118876>
|
||||||
|
fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
|
||||||
|
struct Bounded<'a, 'b: 'static, T>(&'a mut T, [&'b (); 0]);
|
||||||
|
let mut n: Box<dyn FnMut(&mut T) -> Bounded<'static, '_, T>> = Box::new(|x| Bounded(x, []));
|
||||||
|
n(input).0
|
||||||
|
//~^ ERROR borrowed data escapes outside of function
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
47
tests/ui/nll/check-normalized-sig-for-wf.stderr
Normal file
47
tests/ui/nll/check-normalized-sig-for-wf.stderr
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
error[E0597]: `s` does not live long enough
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:7:7
|
||||||
|
|
|
||||||
|
LL | s: String,
|
||||||
|
| - binding `s` declared here
|
||||||
|
...
|
||||||
|
LL | f(&s).0
|
||||||
|
| --^^-
|
||||||
|
| | |
|
||||||
|
| | borrowed value does not live long enough
|
||||||
|
| argument requires that `s` is borrowed for `'static`
|
||||||
|
LL |
|
||||||
|
LL | }
|
||||||
|
| - `s` dropped here while still borrowed
|
||||||
|
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:15:5
|
||||||
|
|
|
||||||
|
LL | fn extend<T>(input: &T) -> &'static T {
|
||||||
|
| ----- - let's call the lifetime of this reference `'1`
|
||||||
|
| |
|
||||||
|
| `input` is a reference that is only valid in the function body
|
||||||
|
...
|
||||||
|
LL | n(input).0
|
||||||
|
| ^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `input` escapes the function body here
|
||||||
|
| argument requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:23:5
|
||||||
|
|
|
||||||
|
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
|
||||||
|
| -- ----- `input` is a reference that is only valid in the function body
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | n(input).0
|
||||||
|
| ^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `input` escapes the function body here
|
||||||
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0521, E0597.
|
||||||
|
For more information about an error, try `rustc --explain E0521`.
|
@ -20,5 +20,5 @@ default impl<T> Foo for T {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("{}", MyStruct.foo_one());
|
println!("{}", MyStruct.foo_one());
|
||||||
//~^ ERROR the method
|
//~^ ERROR no method named `foo_one` found for struct `MyStruct` in the current scope
|
||||||
}
|
}
|
||||||
|
@ -8,27 +8,15 @@ LL | #![feature(specialization)]
|
|||||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied
|
error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
|
||||||
--> $DIR/specialization-trait-not-implemented.rs:22:29
|
--> $DIR/specialization-trait-not-implemented.rs:22:29
|
||||||
|
|
|
|
||||||
LL | struct MyStruct;
|
LL | struct MyStruct;
|
||||||
| --------------- method `foo_one` not found for this struct because it doesn't satisfy `MyStruct: Foo`
|
| --------------- method `foo_one` not found for this struct
|
||||||
...
|
...
|
||||||
LL | println!("{}", MyStruct.foo_one());
|
LL | println!("{}", MyStruct.foo_one());
|
||||||
| ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds
|
| ^^^^^^^ method not found in `MyStruct`
|
||||||
|
|
|
|
||||||
note: trait bound `MyStruct: Foo` was not satisfied
|
|
||||||
--> $DIR/specialization-trait-not-implemented.rs:14:1
|
|
||||||
|
|
|
||||||
LL | default impl<T> Foo for T {
|
|
||||||
| ^^^^^^^^^^^^^^^^---^^^^^-
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
note: the trait `Foo` must be implemented
|
|
||||||
--> $DIR/specialization-trait-not-implemented.rs:7:1
|
|
||||||
|
|
|
||||||
LL | trait Foo {
|
|
||||||
| ^^^^^^^^^
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
note: `Foo` defines an item `foo_one`, perhaps you need to implement it
|
note: `Foo` defines an item `foo_one`, perhaps you need to implement it
|
||||||
--> $DIR/specialization-trait-not-implemented.rs:7:1
|
--> $DIR/specialization-trait-not-implemented.rs:7:1
|
||||||
|
@ -7,6 +7,7 @@ struct Z;
|
|||||||
default impl S {} //~ ERROR inherent impls cannot be `default`
|
default impl S {} //~ ERROR inherent impls cannot be `default`
|
||||||
|
|
||||||
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
|
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
|
||||||
|
//~^ ERROR `S` cannot be sent between threads safely
|
||||||
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
|
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
|
||||||
//~^ ERROR negative impls cannot be default impls
|
//~^ ERROR negative impls cannot be default impls
|
||||||
|
|
||||||
|
@ -26,8 +26,19 @@ LL | default unsafe impl Send for S {}
|
|||||||
| |
|
| |
|
||||||
| default because of this
|
| default because of this
|
||||||
|
|
||||||
|
error[E0277]: `S` cannot be sent between threads safely
|
||||||
|
--> $DIR/validation.rs:9:1
|
||||||
|
|
|
||||||
|
LL | default unsafe impl Send for S {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `S` cannot be sent between threads safely
|
||||||
|
|
|
||||||
|
= help: the trait `Send` is not implemented for `S`
|
||||||
|
= help: the trait `Send` is implemented for `S`
|
||||||
|
= help: see issue #48214
|
||||||
|
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: impls of auto traits cannot be default
|
error: impls of auto traits cannot be default
|
||||||
--> $DIR/validation.rs:10:15
|
--> $DIR/validation.rs:11:15
|
||||||
|
|
|
|
||||||
LL | default impl !Send for Z {}
|
LL | default impl !Send for Z {}
|
||||||
| ------- ^^^^ auto trait
|
| ------- ^^^^ auto trait
|
||||||
@ -35,17 +46,18 @@ LL | default impl !Send for Z {}
|
|||||||
| default because of this
|
| default because of this
|
||||||
|
|
||||||
error[E0750]: negative impls cannot be default impls
|
error[E0750]: negative impls cannot be default impls
|
||||||
--> $DIR/validation.rs:10:1
|
--> $DIR/validation.rs:11:1
|
||||||
|
|
|
|
||||||
LL | default impl !Send for Z {}
|
LL | default impl !Send for Z {}
|
||||||
| ^^^^^^^ ^
|
| ^^^^^^^ ^
|
||||||
|
|
||||||
error[E0750]: negative impls cannot be default impls
|
error[E0750]: negative impls cannot be default impls
|
||||||
--> $DIR/validation.rs:14:1
|
--> $DIR/validation.rs:15:1
|
||||||
|
|
|
|
||||||
LL | default impl !Tr for S {}
|
LL | default impl !Tr for S {}
|
||||||
| ^^^^^^^ ^
|
| ^^^^^^^ ^
|
||||||
|
|
||||||
error: aborting due to 5 previous errors; 1 warning emitted
|
error: aborting due to 6 previous errors; 1 warning emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0750`.
|
Some errors have detailed explanations: E0277, E0750.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
error[E0275]: overflow evaluating the requirement `T: Trait<_>`
|
error[E0119]: conflicting implementations of trait `Trait<_>`
|
||||||
|
|
--> $DIR/issue-45814.rs:10:1
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
|
|
||||||
note: required for `T` to implement `Trait<_>`
|
|
||||||
--> $DIR/issue-45814.rs:9:20
|
|
||||||
|
|
|
|
||||||
LL | default impl<T, U> Trait<T> for U {}
|
LL | default impl<T, U> Trait<T> for U {}
|
||||||
| ^^^^^^^^ ^
|
| --------------------------------- first implementation here
|
||||||
= note: 128 redundant requirements hidden
|
LL |
|
||||||
= note: required for `T` to implement `Trait<_>`
|
LL | impl<T> Trait<<T as Iterator>::Item> for T {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0119`.
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
error[E0275]: overflow evaluating the requirement `T: Trait<_>`
|
error[E0119]: conflicting implementations of trait `Trait<_>`
|
||||||
|
|
--> $DIR/issue-45814.rs:10:1
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
|
|
||||||
note: required for `T` to implement `Trait<_>`
|
|
||||||
--> $DIR/issue-45814.rs:9:20
|
|
||||||
|
|
|
|
||||||
LL | default impl<T, U> Trait<T> for U {}
|
LL | default impl<T, U> Trait<T> for U {}
|
||||||
| ^^^^^^^^ ^
|
| --------------------------------- first implementation here
|
||||||
= note: 128 redundant requirements hidden
|
LL |
|
||||||
= note: required for `T` to implement `Trait<_>`
|
LL | impl<T> Trait<<T as Iterator>::Item> for T {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0119`.
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//~ ERROR overflow evaluating the requirement `T: Trait<_>`
|
|
||||||
// revisions: current negative
|
// revisions: current negative
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
#![cfg_attr(negative, feature(with_negative_coherence))]
|
#![cfg_attr(negative, feature(with_negative_coherence))]
|
||||||
@ -9,5 +8,6 @@ pub trait Trait<T> {}
|
|||||||
default impl<T, U> Trait<T> for U {}
|
default impl<T, U> Trait<T> for U {}
|
||||||
|
|
||||||
impl<T> Trait<<T as Iterator>::Item> for T {}
|
impl<T> Trait<<T as Iterator>::Item> for T {}
|
||||||
|
//~^ ERROR conflicting implementations of trait `Trait<_>`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -651,6 +651,7 @@ compiler-team = [
|
|||||||
"@petrochenkov",
|
"@petrochenkov",
|
||||||
"@davidtwco",
|
"@davidtwco",
|
||||||
"@estebank",
|
"@estebank",
|
||||||
|
"@lcnr",
|
||||||
"@oli-obk",
|
"@oli-obk",
|
||||||
"@pnkfelix",
|
"@pnkfelix",
|
||||||
"@wesleywiser",
|
"@wesleywiser",
|
||||||
@ -680,7 +681,6 @@ infra-ci = [
|
|||||||
"@Kobzol",
|
"@Kobzol",
|
||||||
]
|
]
|
||||||
rustdoc = [
|
rustdoc = [
|
||||||
"@jsha",
|
|
||||||
"@GuillaumeGomez",
|
"@GuillaumeGomez",
|
||||||
"@notriddle",
|
"@notriddle",
|
||||||
"@fmease",
|
"@fmease",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user