mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
Auto merge of #109714 - matthiaskrgr:rollup-wipns5h, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #109149 (Improve error message when writer is forgotten in write and writeln macro) - #109367 (Streamline fast rejection) - #109548 (AnnotationColumn struct to fix hard tab column numbers in errors) - #109694 (do not panic on failure to acquire jobserver token) - #109705 (new solver: check for intercrate mode when accessing the cache) - #109708 (Specialization involving RPITITs is broken so ignore the diagnostic differences) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
40cd0310db
@ -1452,8 +1452,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
Err(e) => {
|
||||
let msg = &format!("failed to acquire jobserver token: {}", e);
|
||||
shared_emitter.fatal(msg);
|
||||
// Exit the coordinator thread
|
||||
panic!("{}", msg)
|
||||
codegen_done = true;
|
||||
codegen_aborted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +202,10 @@ impl AnnotateSnippetEmitterWriter {
|
||||
annotations: annotations
|
||||
.iter()
|
||||
.map(|annotation| SourceAnnotation {
|
||||
range: (annotation.start_col, annotation.end_col),
|
||||
range: (
|
||||
annotation.start_col.display,
|
||||
annotation.end_col.display,
|
||||
),
|
||||
label: annotation.label.as_deref().unwrap_or_default(),
|
||||
annotation_type: annotation_type_for_level(*level),
|
||||
})
|
||||
|
@ -12,7 +12,9 @@ use Destination::*;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{FileLines, SourceFile, Span};
|
||||
|
||||
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
||||
use crate::snippet::{
|
||||
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
|
||||
};
|
||||
use crate::styled_buffer::StyledBuffer;
|
||||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
@ -858,7 +860,7 @@ impl EmitterWriter {
|
||||
let mut short_start = true;
|
||||
for ann in &line.annotations {
|
||||
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
|
||||
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
|
||||
if source_string.chars().take(ann.start_col.display).all(|c| c.is_whitespace()) {
|
||||
let style = if ann.is_primary {
|
||||
Style::UnderlinePrimary
|
||||
} else {
|
||||
@ -1093,15 +1095,15 @@ impl EmitterWriter {
|
||||
'_',
|
||||
line_offset + pos,
|
||||
width_offset + depth,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
style,
|
||||
);
|
||||
}
|
||||
_ if self.teach => {
|
||||
buffer.set_style_range(
|
||||
line_offset,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.end_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
(code_offset + annotation.end_col.display).saturating_sub(left),
|
||||
style,
|
||||
annotation.is_primary,
|
||||
);
|
||||
@ -1133,7 +1135,7 @@ impl EmitterWriter {
|
||||
for p in line_offset + 1..=line_offset + pos {
|
||||
buffer.putc(
|
||||
p,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
'|',
|
||||
style,
|
||||
);
|
||||
@ -1169,9 +1171,9 @@ impl EmitterWriter {
|
||||
let style =
|
||||
if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary };
|
||||
let (pos, col) = if pos == 0 {
|
||||
(pos + 1, (annotation.end_col + 1).saturating_sub(left))
|
||||
(pos + 1, (annotation.end_col.display + 1).saturating_sub(left))
|
||||
} else {
|
||||
(pos + 2, annotation.start_col.saturating_sub(left))
|
||||
(pos + 2, annotation.start_col.display.saturating_sub(left))
|
||||
};
|
||||
if let Some(ref label) = annotation.label {
|
||||
buffer.puts(line_offset + pos, code_offset + col, label, style);
|
||||
@ -1208,7 +1210,7 @@ impl EmitterWriter {
|
||||
} else {
|
||||
('-', Style::UnderlineSecondary)
|
||||
};
|
||||
for p in annotation.start_col..annotation.end_col {
|
||||
for p in annotation.start_col.display..annotation.end_col.display {
|
||||
buffer.putc(
|
||||
line_offset + 1,
|
||||
(code_offset + p).saturating_sub(left),
|
||||
@ -1459,7 +1461,7 @@ impl EmitterWriter {
|
||||
&annotated_file.file.name,
|
||||
line.line_index
|
||||
),
|
||||
annotations[0].start_col + 1,
|
||||
annotations[0].start_col.file + 1,
|
||||
),
|
||||
Style::LineAndColumn,
|
||||
);
|
||||
@ -1546,7 +1548,7 @@ impl EmitterWriter {
|
||||
buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber);
|
||||
let loc = if let Some(first_line) = annotated_file.lines.first() {
|
||||
let col = if let Some(first_annotation) = first_line.annotations.first() {
|
||||
format!(":{}", first_annotation.start_col + 1)
|
||||
format!(":{}", first_annotation.start_col.file + 1)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@ -1607,8 +1609,8 @@ impl EmitterWriter {
|
||||
let mut span_left_margin = usize::MAX;
|
||||
for line in &annotated_file.lines {
|
||||
for ann in &line.annotations {
|
||||
span_left_margin = min(span_left_margin, ann.start_col);
|
||||
span_left_margin = min(span_left_margin, ann.end_col);
|
||||
span_left_margin = min(span_left_margin, ann.start_col.display);
|
||||
span_left_margin = min(span_left_margin, ann.end_col.display);
|
||||
}
|
||||
}
|
||||
if span_left_margin == usize::MAX {
|
||||
@ -1625,11 +1627,12 @@ impl EmitterWriter {
|
||||
annotated_file.file.get_line(line.line_index - 1).map_or(0, |s| s.len()),
|
||||
);
|
||||
for ann in &line.annotations {
|
||||
span_right_margin = max(span_right_margin, ann.start_col);
|
||||
span_right_margin = max(span_right_margin, ann.end_col);
|
||||
span_right_margin = max(span_right_margin, ann.start_col.display);
|
||||
span_right_margin = max(span_right_margin, ann.end_col.display);
|
||||
// FIXME: account for labels not in the same line
|
||||
let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1);
|
||||
label_right_margin = max(label_right_margin, ann.end_col + label_right);
|
||||
label_right_margin =
|
||||
max(label_right_margin, ann.end_col.display + label_right);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2352,8 +2355,8 @@ impl FileWithAnnotatedLines {
|
||||
depth: 1,
|
||||
line_start: lo.line,
|
||||
line_end: hi.line,
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
start_col: AnnotationColumn::from_loc(&lo),
|
||||
end_col: AnnotationColumn::from_loc(&hi),
|
||||
is_primary,
|
||||
label,
|
||||
overlaps_exactly: false,
|
||||
@ -2361,8 +2364,8 @@ impl FileWithAnnotatedLines {
|
||||
multiline_annotations.push((lo.file, ml));
|
||||
} else {
|
||||
let ann = Annotation {
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
start_col: AnnotationColumn::from_loc(&lo),
|
||||
end_col: AnnotationColumn::from_loc(&hi),
|
||||
is_primary,
|
||||
label,
|
||||
annotation_type: AnnotationType::Singleline,
|
||||
@ -2551,7 +2554,13 @@ fn num_overlap(
|
||||
(b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start)
|
||||
}
|
||||
fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
|
||||
num_overlap(a1.start_col, a1.end_col + padding, a2.start_col, a2.end_col, false)
|
||||
num_overlap(
|
||||
a1.start_col.display,
|
||||
a1.end_col.display + padding,
|
||||
a2.start_col.display,
|
||||
a2.end_col.display,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
fn emit_to_destination(
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code for annotating snippets.
|
||||
|
||||
use crate::Level;
|
||||
use crate::{Level, Loc};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct Line {
|
||||
@ -8,13 +8,39 @@ pub struct Line {
|
||||
pub annotations: Vec<Annotation>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Default)]
|
||||
pub struct AnnotationColumn {
|
||||
/// the (0-indexed) column for *display* purposes, counted in characters, not utf-8 bytes
|
||||
pub display: usize,
|
||||
/// the (0-indexed) column in the file, counted in characters, not utf-8 bytes.
|
||||
///
|
||||
/// this may be different from `self.display`,
|
||||
/// e.g. if the file contains hard tabs, because we convert tabs to spaces for error messages.
|
||||
///
|
||||
/// for example:
|
||||
/// ```text
|
||||
/// (hard tab)hello
|
||||
/// ^ this is display column 4, but file column 1
|
||||
/// ```
|
||||
///
|
||||
/// we want to keep around the correct file offset so that column numbers in error messages
|
||||
/// are correct. (motivated by <https://github.com/rust-lang/rust/issues/109537>)
|
||||
pub file: usize,
|
||||
}
|
||||
|
||||
impl AnnotationColumn {
|
||||
pub fn from_loc(loc: &Loc) -> AnnotationColumn {
|
||||
AnnotationColumn { display: loc.col_display, file: loc.col.0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct MultilineAnnotation {
|
||||
pub depth: usize,
|
||||
pub line_start: usize,
|
||||
pub line_end: usize,
|
||||
pub start_col: usize,
|
||||
pub end_col: usize,
|
||||
pub start_col: AnnotationColumn,
|
||||
pub end_col: AnnotationColumn,
|
||||
pub is_primary: bool,
|
||||
pub label: Option<String>,
|
||||
pub overlaps_exactly: bool,
|
||||
@ -36,7 +62,12 @@ impl MultilineAnnotation {
|
||||
pub fn as_start(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: self.start_col,
|
||||
end_col: self.start_col + 1,
|
||||
end_col: AnnotationColumn {
|
||||
// these might not correspond to the same place anymore,
|
||||
// but that's okay for our purposes
|
||||
display: self.start_col.display + 1,
|
||||
file: self.start_col.file + 1,
|
||||
},
|
||||
is_primary: self.is_primary,
|
||||
label: None,
|
||||
annotation_type: AnnotationType::MultilineStart(self.depth),
|
||||
@ -45,7 +76,12 @@ impl MultilineAnnotation {
|
||||
|
||||
pub fn as_end(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: self.end_col.saturating_sub(1),
|
||||
start_col: AnnotationColumn {
|
||||
// these might not correspond to the same place anymore,
|
||||
// but that's okay for our purposes
|
||||
display: self.end_col.display.saturating_sub(1),
|
||||
file: self.end_col.file.saturating_sub(1),
|
||||
},
|
||||
end_col: self.end_col,
|
||||
is_primary: self.is_primary,
|
||||
label: self.label.clone(),
|
||||
@ -55,8 +91,8 @@ impl MultilineAnnotation {
|
||||
|
||||
pub fn as_line(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: 0,
|
||||
end_col: 0,
|
||||
start_col: Default::default(),
|
||||
end_col: Default::default(),
|
||||
is_primary: self.is_primary,
|
||||
label: None,
|
||||
annotation_type: AnnotationType::MultilineLine(self.depth),
|
||||
@ -92,14 +128,14 @@ pub enum AnnotationType {
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct Annotation {
|
||||
/// Start column, 0-based indexing -- counting *characters*, not
|
||||
/// utf-8 bytes. Note that it is important that this field goes
|
||||
/// Start column.
|
||||
/// Note that it is important that this field goes
|
||||
/// first, so that when we sort, we sort orderings by start
|
||||
/// column.
|
||||
pub start_col: usize,
|
||||
pub start_col: AnnotationColumn,
|
||||
|
||||
/// End column within the line (exclusive)
|
||||
pub end_col: usize,
|
||||
pub end_col: AnnotationColumn,
|
||||
|
||||
/// Is this annotation derived from primary span
|
||||
pub is_primary: bool,
|
||||
@ -118,12 +154,13 @@ impl Annotation {
|
||||
matches!(self.annotation_type, AnnotationType::MultilineLine(_))
|
||||
}
|
||||
|
||||
/// Length of this annotation as displayed in the stderr output
|
||||
pub fn len(&self) -> usize {
|
||||
// Account for usize underflows
|
||||
if self.end_col > self.start_col {
|
||||
self.end_col - self.start_col
|
||||
if self.end_col.display > self.start_col.display {
|
||||
self.end_col.display - self.start_col.display
|
||||
} else {
|
||||
self.start_col - self.end_col
|
||||
self.start_col.display - self.end_col.display
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,6 +245,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
None
|
||||
}
|
||||
|
||||
fn suggest_missing_writer(
|
||||
&self,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
args: (&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>]),
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
|
||||
let mut err =
|
||||
struct_span_err!(self.tcx.sess, args.0.span, E0599, "cannot write into `{}`", ty_str);
|
||||
err.span_note(
|
||||
args.0.span,
|
||||
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
|
||||
);
|
||||
if let ExprKind::Lit(_) = args.0.kind {
|
||||
err.span_help(
|
||||
args.0.span.shrink_to_lo(),
|
||||
"a writer is needed before this format string",
|
||||
);
|
||||
};
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
pub fn report_no_match_method_error(
|
||||
&self,
|
||||
mut span: Span,
|
||||
@ -323,16 +345,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0599,
|
||||
"no {} named `{}` found for {} `{}` in the current scope",
|
||||
item_kind,
|
||||
item_name,
|
||||
rcvr_ty.prefix_string(self.tcx),
|
||||
ty_str_reported,
|
||||
);
|
||||
let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.map_or(false, |def_id| {
|
||||
tcx.is_diagnostic_item(sym::write_macro, def_id)
|
||||
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
|
||||
}) && item_name.name == Symbol::intern("write_fmt");
|
||||
let mut err = if is_write
|
||||
&& let Some(args) = args
|
||||
{
|
||||
self.suggest_missing_writer(rcvr_ty, args)
|
||||
} else {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0599,
|
||||
"no {} named `{}` found for {} `{}` in the current scope",
|
||||
item_kind,
|
||||
item_name,
|
||||
rcvr_ty.prefix_string(self.tcx),
|
||||
ty_str_reported,
|
||||
)
|
||||
};
|
||||
if tcx.sess.source_map().is_multiline(sugg_span) {
|
||||
err.span_label(sugg_span.with_hi(span.lo()), "");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::mir::Mutability;
|
||||
use crate::ty::subst::GenericArgKind;
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
@ -188,22 +188,24 @@ pub struct DeepRejectCtxt {
|
||||
}
|
||||
|
||||
impl DeepRejectCtxt {
|
||||
pub fn generic_args_may_unify<'tcx>(
|
||||
pub fn substs_refs_may_unify<'tcx>(
|
||||
self,
|
||||
obligation_arg: ty::GenericArg<'tcx>,
|
||||
impl_arg: ty::GenericArg<'tcx>,
|
||||
obligation_substs: SubstsRef<'tcx>,
|
||||
impl_substs: SubstsRef<'tcx>,
|
||||
) -> bool {
|
||||
match (obligation_arg.unpack(), impl_arg.unpack()) {
|
||||
// We don't fast reject based on regions for now.
|
||||
(GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
|
||||
(GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
|
||||
self.types_may_unify(obl, imp)
|
||||
iter::zip(obligation_substs, impl_substs).all(|(obl, imp)| {
|
||||
match (obl.unpack(), imp.unpack()) {
|
||||
// We don't fast reject based on regions for now.
|
||||
(GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
|
||||
(GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
|
||||
self.types_may_unify(obl, imp)
|
||||
}
|
||||
(GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
|
||||
self.consts_may_unify(obl, imp)
|
||||
}
|
||||
_ => bug!("kind mismatch: {obl} {imp}"),
|
||||
}
|
||||
(GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
|
||||
self.consts_may_unify(obl, imp)
|
||||
}
|
||||
_ => bug!("kind mismatch: {obligation_arg} {impl_arg}"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -> bool {
|
||||
@ -258,9 +260,7 @@ impl DeepRejectCtxt {
|
||||
},
|
||||
ty::Adt(obl_def, obl_substs) => match k {
|
||||
&ty::Adt(impl_def, impl_substs) => {
|
||||
obl_def == impl_def
|
||||
&& iter::zip(obl_substs, impl_substs)
|
||||
.all(|(obl, imp)| self.generic_args_may_unify(obl, imp))
|
||||
obl_def == impl_def && self.substs_refs_may_unify(obl_substs, impl_substs)
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
@ -17,7 +17,6 @@ use rustc_middle::ty::ProjectionPredicate;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
|
||||
use rustc_span::{sym, DUMMY_SP};
|
||||
use std::iter;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
@ -144,9 +143,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
||||
if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs)
|
||||
.any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
|
||||
{
|
||||
if !drcx.substs_refs_may_unify(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,22 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
self.mode
|
||||
}
|
||||
|
||||
/// We do not use the global cache during coherence.
|
||||
///
|
||||
/// The trait solver behavior is different for coherence
|
||||
/// so we would have to add the solver mode to the cache key.
|
||||
/// This is probably not worth it as trait solving during
|
||||
/// coherence tends to already be incredibly fast.
|
||||
///
|
||||
/// We could add another global cache for coherence instead,
|
||||
/// but that's effort so let's only do it if necessary.
|
||||
pub(super) fn should_use_global_cache(&self) -> bool {
|
||||
match self.mode {
|
||||
SolverMode::Normal => true,
|
||||
SolverMode::Coherence => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_empty(&self) -> bool {
|
||||
self.stack.is_empty() && self.provisional_cache.is_empty()
|
||||
}
|
||||
@ -191,8 +207,10 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
canonical_goal: CanonicalGoal<'tcx>,
|
||||
mut loop_body: impl FnMut(&mut Self) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_goal, tcx) {
|
||||
return result;
|
||||
if self.should_use_global_cache() {
|
||||
if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_goal, tcx) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
match self.try_push_stack(tcx, canonical_goal) {
|
||||
@ -252,9 +270,8 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
// dependencies, our non-root goal may no longer appear as child of the root goal.
|
||||
//
|
||||
// See https://github.com/rust-lang/rust/pull/108071 for some additional context.
|
||||
let should_cache_globally = matches!(self.solver_mode(), SolverMode::Normal)
|
||||
&& (!self.overflow_data.did_overflow() || self.stack.is_empty());
|
||||
if should_cache_globally {
|
||||
let can_cache = !self.overflow_data.did_overflow() || self.stack.is_empty();
|
||||
if self.should_use_global_cache() && can_cache {
|
||||
tcx.new_solver_evaluation_cache.insert(
|
||||
current_goal.goal,
|
||||
dep_node,
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
|
||||
|
||||
use std::iter;
|
||||
|
||||
use super::{assembly, EvalCtxt, SolverMode};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::LangItem;
|
||||
@ -41,9 +39,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
||||
if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs)
|
||||
.any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
|
||||
{
|
||||
if !drcx.substs_refs_may_unify(
|
||||
goal.predicate.trait_ref.substs,
|
||||
impl_trait_ref.skip_binder().substs,
|
||||
) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,9 @@ pub fn overlapping_impls(
|
||||
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
|
||||
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
|
||||
let may_overlap = match (impl1_ref, impl2_ref) {
|
||||
(Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs)
|
||||
.all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
|
||||
(Some(a), Some(b)) => {
|
||||
drcx.substs_refs_may_unify(a.skip_binder().substs, b.skip_binder().substs)
|
||||
}
|
||||
(None, None) => {
|
||||
let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
|
||||
let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
|
||||
|
@ -11,7 +11,7 @@ use hir::LangItem;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
|
||||
use rustc_middle::ty::fast_reject::TreatProjections;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
|
||||
use crate::traits;
|
||||
@ -344,6 +344,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
||||
let obligation_substs = obligation.predicate.skip_binder().trait_ref.substs;
|
||||
self.tcx().for_each_relevant_impl(
|
||||
obligation.predicate.def_id(),
|
||||
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
||||
@ -352,7 +354,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// consider a "quick reject". This avoids creating more types
|
||||
// and so forth that we need to.
|
||||
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
|
||||
if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
|
||||
if !drcx.substs_refs_may_unify(obligation_substs, impl_trait_ref.0.substs) {
|
||||
return;
|
||||
}
|
||||
if self.reject_fn_ptr_impls(
|
||||
|
@ -45,7 +45,6 @@ use rustc_infer::traits::TraitEngineExt;
|
||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::SubstsRef;
|
||||
@ -2533,19 +2532,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
Ok(Normalized { value: impl_substs, obligations: nested_obligations })
|
||||
}
|
||||
|
||||
fn fast_reject_trait_refs(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>,
|
||||
) -> bool {
|
||||
// We can avoid creating type variables and doing the full
|
||||
// substitution if we find that any of the input types, when
|
||||
// simplified, do not match.
|
||||
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
||||
iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs)
|
||||
.any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp))
|
||||
}
|
||||
|
||||
/// Normalize `where_clause_trait_ref` and try to match it against
|
||||
/// `obligation`. If successful, return any predicates that
|
||||
/// result from the normalization.
|
||||
|
8
tests/run-make/jobserver-error/Makefile
Normal file
8
tests/run-make/jobserver-error/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
# only-linux
|
||||
|
||||
# Test compiler behavior in case: `jobserver-auth` points to correct pipe which is not jobserver.
|
||||
|
||||
all:
|
||||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff jobserver.stderr -
|
4
tests/run-make/jobserver-error/jobserver.stderr
Normal file
4
tests/run-make/jobserver-error/jobserver.stderr
Normal file
@ -0,0 +1,4 @@
|
||||
error: failed to acquire jobserver token: early EOF on jobserver pipe
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:4:12
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -8,7 +8,7 @@ LL | #![feature(async_fn_in_trait)]
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: async associated function in trait cannot be specialized
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:14:5
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:16:5
|
||||
|
|
||||
LL | default async fn foo(_: T) -> &'static str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
@ -0,0 +1,34 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0053]: method `foo` has an incompatible type for trait
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:16:35
|
||||
|
|
||||
LL | default async fn foo(_: T) -> &'static str {
|
||||
| ^^^^^^^^^^^^ expected associated type, found future
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:12:27
|
||||
|
|
||||
LL | async fn foo(_: T) -> &'static str;
|
||||
| ^^^^^^^^^^^^
|
||||
= note: expected signature `fn(_) -> impl Future<Output = &'static str>`
|
||||
found signature `fn(_) -> impl Future<Output = &'static str>`
|
||||
|
||||
error: async associated function in trait cannot be specialized
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:16:5
|
||||
|
|
||||
LL | default async fn foo(_: T) -> &'static str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
@ -1,5 +1,7 @@
|
||||
// edition: 2021
|
||||
// known-bug: #108309
|
||||
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![feature(min_specialization)]
|
||||
|
@ -0,0 +1,6 @@
|
||||
// ignore-tidy-tab
|
||||
|
||||
pub struct S;
|
||||
impl S {
|
||||
fn method(&self) {}
|
||||
}
|
12
tests/ui/diagnostic-width/tab-column-numbers.rs
Normal file
12
tests/ui/diagnostic-width/tab-column-numbers.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// Test for #109537: ensure that column numbers are correctly generated when using hard tabs.
|
||||
// aux-build:tab_column_numbers.rs
|
||||
|
||||
// ignore-tidy-tab
|
||||
|
||||
extern crate tab_column_numbers;
|
||||
|
||||
fn main() {
|
||||
let s = tab_column_numbers::S;
|
||||
s.method();
|
||||
//~^ ERROR method `method` is private
|
||||
}
|
14
tests/ui/diagnostic-width/tab-column-numbers.stderr
Normal file
14
tests/ui/diagnostic-width/tab-column-numbers.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0624]: method `method` is private
|
||||
--> $DIR/tab-column-numbers.rs:10:4
|
||||
|
|
||||
LL | s.method();
|
||||
| ^^^^^^ private method
|
||||
|
|
||||
::: $DIR/auxiliary/tab_column_numbers.rs:5:3
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ---------------- private method defined here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0624`.
|
17
tests/ui/macros/missing-writer.rs
Normal file
17
tests/ui/macros/missing-writer.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Check error for missing writer in writeln! and write! macro
|
||||
fn main() {
|
||||
let x = 1;
|
||||
let y = 2;
|
||||
write!("{}_{}", x, y);
|
||||
//~^ ERROR format argument must be a string literal
|
||||
//~| HELP you might be missing a string literal to format with
|
||||
//~| ERROR cannot write into `&'static str`
|
||||
//~| NOTE must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
|
||||
//~| HELP a writer is needed before this format string
|
||||
writeln!("{}_{}", x, y);
|
||||
//~^ ERROR format argument must be a string literal
|
||||
//~| HELP you might be missing a string literal to format with
|
||||
//~| ERROR cannot write into `&'static str`
|
||||
//~| NOTE must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
|
||||
//~| HELP a writer is needed before this format string
|
||||
}
|
59
tests/ui/macros/missing-writer.stderr
Normal file
59
tests/ui/macros/missing-writer.stderr
Normal file
@ -0,0 +1,59 @@
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/missing-writer.rs:5:21
|
||||
|
|
||||
LL | write!("{}_{}", x, y);
|
||||
| ^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | write!("{}_{}", "{} {}", x, y);
|
||||
| ++++++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/missing-writer.rs:11:23
|
||||
|
|
||||
LL | writeln!("{}_{}", x, y);
|
||||
| ^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | writeln!("{}_{}", "{} {}", x, y);
|
||||
| ++++++++
|
||||
|
||||
error[E0599]: cannot write into `&'static str`
|
||||
--> $DIR/missing-writer.rs:5:12
|
||||
|
|
||||
LL | write!("{}_{}", x, y);
|
||||
| -------^^^^^^^------- method not found in `&str`
|
||||
|
|
||||
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
|
||||
--> $DIR/missing-writer.rs:5:12
|
||||
|
|
||||
LL | write!("{}_{}", x, y);
|
||||
| ^^^^^^^
|
||||
help: a writer is needed before this format string
|
||||
--> $DIR/missing-writer.rs:5:12
|
||||
|
|
||||
LL | write!("{}_{}", x, y);
|
||||
| ^
|
||||
|
||||
error[E0599]: cannot write into `&'static str`
|
||||
--> $DIR/missing-writer.rs:11:14
|
||||
|
|
||||
LL | writeln!("{}_{}", x, y);
|
||||
| ---------^^^^^^^------- method not found in `&str`
|
||||
|
|
||||
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
|
||||
--> $DIR/missing-writer.rs:11:14
|
||||
|
|
||||
LL | writeln!("{}_{}", x, y);
|
||||
| ^^^^^^^
|
||||
help: a writer is needed before this format string
|
||||
--> $DIR/missing-writer.rs:11:14
|
||||
|
|
||||
LL | writeln!("{}_{}", x, y);
|
||||
| ^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -21,18 +21,22 @@ note: required by a bound in `BufWriter`
|
||||
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
|
||||
|
||||
error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
|
||||
--> $DIR/mut-borrow-needed-by-trait.rs:21:5
|
||||
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
|
||||
|
|
||||
LL | writeln!(fp, "hello world").unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
|
||||
| ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
|
||||
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
|
||||
|
|
||||
= note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
|
||||
|
|
||||
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
|
||||
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
|
||||
|
|
||||
LL | writeln!(fp, "hello world").unwrap();
|
||||
| ^^
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`&dyn std::io::Write: std::io::Write`
|
||||
which is required by `BufWriter<&dyn std::io::Write>: std::io::Write`
|
||||
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user