Auto merge of #106851 - matthiaskrgr:rollup-d9dz3yp, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #106046 (Fix mir-opt tests for big-endian platforms)
 - #106470 (tidy: Don't include wasm32 in compiler dependency check)
 - #106566 (Emit a single error for contiguous sequences of unknown tokens)
 - #106644 (Update the wasi-libc used for the wasm32-wasi target)
 - #106665 (Add note when `FnPtr` vs. `FnDef` impl trait)
 - #106752 (Emit a hint for bad call return types due to generic arguments)
 - #106788 (Tweak E0599 and elaborate_predicates)
 - #106831 (Use GitHub yaml templates for ICE, Docs and Diagnostics tickets)
 - #106846 (Improve some comments and names in parser)
 - #106848 (Fix wrong path in triage bot autolabel for wg-trait-solver-refactor)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-01-14 14:50:53 +00:00
commit 4b51adf6ff
54 changed files with 1082 additions and 307 deletions

View File

@ -1,46 +0,0 @@
---
name: Diagnostic issue
about: Create a bug report or feature request for a change to `rustc`'s error output
labels: A-diagnostics, T-compiler
---
<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
the problematic output to occur.
-->
Given the following code: <!-- Please provide a link to play.rust-lang.org -->
```rust
<code>
```
The current output is:
```
<rustc output>
```
<!-- The following is not always necessary. -->
Ideally the output should look like:
```
<proposed output>
```
<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->
<!--
If dramatically different output is caused by small changes, consider also
adding them here.
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->

65
.github/ISSUE_TEMPLATE/diagnostics.yaml vendored Normal file
View File

@ -0,0 +1,65 @@
name: Diagnostic issue
description: Create a bug report or feature request for a change to `rustc`'s error output
labels: ["A-diagnostics", "T-compiler"]
body:
- type: markdown
attributes:
value: |
Thank you for filing a diagnostics bug report! 🐛
Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug.
If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur.
- type: textarea
id: code
attributes:
label: Code
description: Please provide code that can reproduce the problem
placeholder: code
render: Rust
validations:
required: true
- type: textarea
id: output
attributes:
label: Current output
description: Please provide the `rustc` output you see
placeholder: rustc output
render: Shell
validations:
required: true
- type: textarea
id: desired-output
attributes:
label: Desired output
description: Please provide what the output *should* be
placeholder: proposed output
render: Shell
validations:
required: false
- type: textarea
id: rationale
attributes:
label: Rationale and extra context
description: If the problem is not self-explanatory, please provide a rationale for the change.
validations:
required: false
- type: textarea
id: other-output
attributes:
label: Other cases
description: If dramatically different output is caused by small changes, consider also adding them here.
render: Rust
validations:
required: false
- type: markdown
attributes:
value: |
If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition.
- type: textarea
id: extra
attributes:
label: Anything else?
description: If you have more details you want to give us to reproduce this issue, please add it here
validations:
required: false

View File

@ -1,31 +0,0 @@
---
name: Documentation problem
about: Create a report for a documentation problem.
labels: A-docs
---
<!--
Thank you for finding a documentation problem! 📚
Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
Note: If your issue is for one of these, please use their dedicated issue tracker instead:
- The Rust Book: https://github.com/rust-lang/book/issues
- Rust by Example: https://github.com/rust-lang/rust-by-example/issues
- The Edition Guide: https://github.com/rust-lang/edition-guide/issues
- The Cargo Book: https://github.com/rust-lang/cargo/issues
- The Clippy Book: https://github.com/rust-lang/rust-clippy/issues
- The Reference: https://github.com/rust-lang/reference/issues
- The Rustonomicon: https://github.com/rust-lang/nomicon/issues
- The Embedded Book: https://github.com/rust-embedded/book/issues
All other documentation issues should be filed here.
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
-->
### Location
### Summary

View File

@ -0,0 +1,38 @@
name: Documentation problem
description: Create a report for a documentation problem.
labels: ["A-docs"]
body:
- type: markdown
attributes:
value: |
Thank you for finding a documentation problem! 📚
Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
Note: If your issue is for one of these, please use their dedicated issue tracker instead:
- [The Rust Book](https://github.com/rust-lang/book/issues)
- [Rust by Example](https://github.com/rust-lang/rust-by-example/issues)
- [The Edition Guide](https://github.com/rust-lang/edition-guide/issues)
- [The Cargo Book](https://github.com/rust-lang/cargo/issues)
- [The Clippy Book](https://github.com/rust-lang/rust-clippy/issues)
- [The Reference](https://github.com/rust-lang/reference/issues)
- [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
- [The Embedded Book](https://github.com/rust-embedded/book/issues)
All other documentation issues should be filed here.
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
- type: textarea
id: location
attributes:
label: Location
validations:
required: true
- type: textarea
id: summary
attributes:
label: Summary
validations:
required: true

View File

@ -1,52 +0,0 @@
---
name: Internal Compiler Error
about: Create a report for an internal compiler error in rustc.
labels: C-bug, I-ICE, T-compiler
---
<!--
Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
how to create smaller examples.
http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
-->
### Code
```Rust
<code>
```
### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->
`rustc --version --verbose`:
```
<version>
```
### Error output
```
<output>
```
<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary><strong>Backtrace</strong></summary>
<p>
```
<backtrace>
```
</p>
</details>

82
.github/ISSUE_TEMPLATE/ice.yaml vendored Normal file
View File

@ -0,0 +1,82 @@
name: Internal Compiler Error
description: Create a report for an internal compiler error in `rustc`
labels: ["C-bug", "I-ICE", "T-compiler"]
title: "[ICE]: "
body:
- type: markdown
attributes:
value: |
Thank you for finding an Internal Compiler Error! 🧊
If possible, try to provide a minimal verifiable example.
You can read "[Rust Bug Minimization Patterns](http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/)" for how to create smaller examples.
- type: textarea
id: code
attributes:
label: Code
description: Please provide code or a link to a repository that can reproduce the problem
placeholder: code
render: Rust
validations:
required: false
- type: checkboxes
attributes:
label: Affected release channels
description: If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions
options:
- label: Previous Stable
required: false
- label: Current Stable
required: false
- label: Current Beta
required: false
- label: Current Nightly
required: false
- type: textarea
id: version
attributes:
label: Rust Version
description: Please provide the `rustc` version, `rustc --version --verbose`
placeholder: |
$ rustc --version --verbose
rustc 1.XX.Y (SHORTHASH DATE)
binary: rustc
commit-hash: LONGHASHVALUE
commit-date: DATE
host: PLATFORMTRIPLE
release: 1.XX.Y
LLVM version: XX.YY.ZZ
render: Shell
validations:
required: true
- type: textarea
id: output
attributes:
label: Current error output
description: Please provide the `rustc` output you see
placeholder: output
render: Shell
validations:
required: false
- type: textarea
id: backtrace
attributes:
label: Backtrace
description: Include a backtrace in the code block by setting `RUST_BACKTRACE=full` in your environment, e.g. `RUST_BACKTRACE=full cargo build`
render: Shell
validations:
required: true
- type: textarea
id: extra
attributes:
label: Anything else?
description: If you have more details you want to give us to reproduce this issue, please add it here
validations:
required: false

View File

@ -5601,6 +5601,7 @@ dependencies = [
name = "tidy"
version = "0.1.0"
dependencies = [
"cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.14.0",
"ignore",
"lazy_static",

View File

@ -85,6 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty);
}
/// Requires that the two types unify, and prints an error message if
@ -1941,4 +1942,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_label(block.span, "this block is missing a tail expression");
}
}
fn check_wrong_return_type_due_to_generic_arg(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
checked_ty: Ty<'tcx>,
) {
let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; };
enum CallableKind {
Function,
Method,
Constructor,
}
let mut maybe_emit_help = |def_id: hir::def_id::DefId,
callable: rustc_span::symbol::Ident,
args: &[hir::Expr<'_>],
kind: CallableKind| {
let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
let fn_ty = self.tcx.bound_type_of(def_id).0;
if !fn_ty.is_fn() {
return;
}
let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; };
if matches!(arg.kind(), ty::Param(_))
&& fn_sig.output().contains(arg)
&& self.node_ty(args[arg_idx].hir_id) == checked_ty
{
let mut multi_span: MultiSpan = parent_expr.span.into();
multi_span.push_span_label(
args[arg_idx].span,
format!(
"this argument influences the {} of `{}`",
if matches!(kind, CallableKind::Constructor) {
"type"
} else {
"return type"
},
callable
),
);
err.span_help(
multi_span,
format!(
"the {} `{}` due to the type of the argument passed",
match kind {
CallableKind::Function => "return type of this call is",
CallableKind::Method => "return type of this call is",
CallableKind::Constructor => "type constructed contains",
},
checked_ty
),
);
}
};
match parent_expr.kind {
hir::ExprKind::Call(fun, args) => {
let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; };
let hir::def::Res::Def(kind, def_id) = path.res else { return; };
let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) {
CallableKind::Constructor
} else {
CallableKind::Function
};
maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind);
}
hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; };
maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
}
_ => return,
}
}
}

View File

@ -1587,11 +1587,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let o = self.resolve_vars_if_possible(o);
if !self.predicate_may_hold(&o) {
result = ProbeResult::NoMatch;
possibly_unsatisfied_predicates.push((
o.predicate,
None,
Some(o.cause),
));
let parent_o = o.clone();
let implied_obligations =
traits::elaborate_obligations(self.tcx, vec![o]);
for o in implied_obligations {
let parent = if o == parent_o {
None
} else {
if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
== self.tcx.lang_items().sized_trait()
{
// We don't care to talk about implicit `Sized` bounds.
continue;
}
Some(parent_o.predicate)
};
if !self.predicate_may_hold(&o) {
possibly_unsatisfied_predicates.push((
o.predicate,
parent,
Some(o.cause),
));
}
}
}
}
}

View File

@ -505,19 +505,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => None,
};
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
if let Some(g) = kind.generics() {
let key = (
g.tail_span_for_predicate_suggestion(),
g.add_where_or_trailing_comma(),
);
type_params
.entry(key)
.or_insert_with(FxHashSet::default)
.insert(obligation.to_owned());
}
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
&& let Some(g) = kind.generics()
{
let key = (
g.tail_span_for_predicate_suggestion(),
g.add_where_or_trailing_comma(),
);
type_params
.entry(key)
.or_insert_with(FxHashSet::default)
.insert(obligation.to_owned());
return true;
}
}
false
};
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
let msg = format!(
@ -692,7 +694,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"auto trait is invoked with no method error, but no error reported?",
);
}
Some(_) => unreachable!(),
Some(Node::Item(hir::Item {
ident, kind: hir::ItemKind::Trait(..), ..
})) => {
skip_list.insert(p);
let entry = spanned_predicates.entry(ident.span);
let entry = entry.or_insert_with(|| {
(FxHashSet::default(), FxHashSet::default(), Vec::new())
});
entry.0.insert(cause.span);
entry.1.insert((ident.span, ""));
entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
entry.2.push(p);
}
Some(node) => unreachable!("encountered `{node:?}`"),
None => (),
}
}
@ -719,19 +734,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
unsatisfied_bounds = true;
}
let mut suggested_bounds = FxHashSet::default();
// The requirements that didn't have an `impl` span to show.
let mut bound_list = unsatisfied_predicates
.iter()
.filter_map(|(pred, parent_pred, _cause)| {
let mut suggested = false;
format_pred(*pred).map(|(p, self_ty)| {
collect_type_param_suggestions(self_ty, *pred, &p);
if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
// We don't suggest `PartialEq` when we already suggest `Eq`.
} else if !suggested_bounds.contains(pred) {
if collect_type_param_suggestions(self_ty, *pred, &p) {
suggested = true;
suggested_bounds.insert(pred);
}
}
(
match parent_pred {
None => format!("`{}`", &p),
Some(parent_pred) => match format_pred(*parent_pred) {
None => format!("`{}`", &p),
Some((parent_p, _)) => {
collect_type_param_suggestions(self_ty, *parent_pred, &p);
if !suggested
&& !suggested_bounds.contains(pred)
&& !suggested_bounds.contains(parent_pred)
{
if collect_type_param_suggestions(
self_ty,
*parent_pred,
&p,
) {
suggested_bounds.insert(pred);
}
}
format!("`{}`\nwhich is required by `{}`", p, parent_p)
}
},

View File

@ -1,7 +1,7 @@
use smallvec::smallvec;
use crate::infer::outlives::components::{push_outlives_components, Component};
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{self, Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::{self, ToPredicate, TyCtxt};
use rustc_span::symbol::Ident;
@ -145,16 +145,28 @@ impl<'tcx> Elaborator<'tcx> {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
let obligations = predicates.predicates.iter().map(|&(mut pred, _)| {
let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
// when parent predicate is non-const, elaborate it to non-const predicates.
if data.constness == ty::BoundConstness::NotConst {
pred = pred.without_const(tcx);
}
let cause = obligation.cause.clone().derived_cause(
bound_predicate.rebind(data),
|derived| {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
impl_def_id: data.def_id(),
span,
},
))
},
);
predicate_obligation(
pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
obligation.param_env,
obligation.cause.clone(),
cause,
)
});
debug!(?data, ?obligations, "super_predicates");

View File

@ -79,7 +79,7 @@ impl<'a> StringReader<'a> {
/// preceded by whitespace.
fn next_token(&mut self) -> (Token, bool) {
let mut preceded_by_whitespace = false;
let mut swallow_next_invalid = 0;
// Skip trivial (whitespace & comments) tokens
loop {
let token = self.cursor.advance_token();
@ -232,19 +232,34 @@ impl<'a> StringReader<'a> {
rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
let c = self.str_from(start).chars().next().unwrap();
// Don't emit diagnostics for sequences of the same invalid token
if swallow_next_invalid > 0 {
swallow_next_invalid -= 1;
continue;
}
let mut it = self.str_from_to_end(start).chars();
let c = it.next().unwrap();
let repeats = it.take_while(|c1| *c1 == c).count();
let mut err =
self.struct_err_span_char(start, self.pos, "unknown start of token", c);
self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c);
// FIXME: the lexer could be used to turn the ASCII version of unicode
// homoglyphs, instead of keeping a table in `check_for_substitution`into the
// token. Ideally, this should be inside `rustc_lexer`. However, we should
// first remove compound tokens like `<<` from `rustc_lexer`, and then add
// fancier error recovery to it, as there will be less overall work to do this
// way.
let token = unicode_chars::check_for_substitution(self, start, c, &mut err);
let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1);
if c == '\x00' {
err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
}
if repeats > 0 {
if repeats == 1 {
err.note(format!("character appears once more"));
} else {
err.note(format!("character appears {repeats} more times"));
}
swallow_next_invalid = repeats;
}
err.emit();
if let Some(token) = token {
token
@ -486,6 +501,11 @@ impl<'a> StringReader<'a> {
&self.src[self.src_index(start)..self.src_index(end)]
}
/// Slice of the source text spanning from `start` until the end
fn str_from_to_end(&self, start: BytePos) -> &str {
&self.src[self.src_index(start)..]
}
fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! {
match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) {
Err(RawStrError::InvalidStarter { bad_char }) => {

View File

@ -337,10 +337,11 @@ pub(super) fn check_for_substitution<'a>(
pos: BytePos,
ch: char,
err: &mut Diagnostic,
count: usize,
) -> Option<token::TokenKind> {
let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8()));
let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count));
let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else {
let msg = format!("substitution character not found for '{}'", ch);
@ -369,7 +370,12 @@ pub(super) fn check_for_substitution<'a>(
"Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
ch, u_name, ascii_char, ascii_name
);
err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect);
err.span_suggestion(
span,
&msg,
ascii_char.to_string().repeat(count),
Applicability::MaybeIncorrect,
);
}
token.clone()
}

View File

@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
pub(super) enum LhsExpr {
NotYetParsed,
AttributesParsed(AttrWrapper),
AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
AlreadyParsed { expr: P<Expr>, starts_statement: bool },
}
impl From<Option<AttrWrapper>> for LhsExpr {
@ -97,11 +97,11 @@ impl From<Option<AttrWrapper>> for LhsExpr {
}
impl From<P<Expr>> for LhsExpr {
/// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed(expr)`.
/// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed { expr, starts_statement: false }`.
///
/// This conversion does not allocate.
fn from(expr: P<Expr>) -> Self {
LhsExpr::AlreadyParsed(expr, false)
LhsExpr::AlreadyParsed { expr, starts_statement: false }
}
}
@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
lhs: LhsExpr,
) -> PResult<'a, P<Expr>> {
let mut starts_stmt = false;
let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs {
starts_stmt = starts_statement;
expr
} else {
@ -562,17 +562,23 @@ impl<'a> Parser<'a> {
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
match this.token.uninterpolate().kind {
token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr`
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr`
// `!expr`
token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
// `~expr`
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
// `-expr`
token::BinOp(token::Minus) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
} // `-expr`
}
// `*expr`
token::BinOp(token::Star) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
} // `*expr`
}
// `&expr` and `&&expr`
token::BinOp(token::And) | token::AndAnd => {
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
}
// `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
let mut err =
LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
@ -587,7 +593,7 @@ impl<'a> Parser<'a> {
this.bump();
this.parse_prefix_expr(None)
} // `+expr`
}
// Recover from `++x`:
token::BinOp(token::Plus)
if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
@ -624,7 +630,7 @@ impl<'a> Parser<'a> {
Ok((span, self.mk_unary(op, expr)))
}
// Recover on `!` suggesting for bitwise negation instead.
/// Recover on `~expr` in favor of `!expr`.
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.sess.emit_err(TildeAsUnaryOperator(lo));
@ -651,7 +657,6 @@ impl<'a> Parser<'a> {
/// Recover on `not expr` in favor of `!expr`.
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
// Emit the error...
let negated_token = self.look_ahead(1, |t| t.clone());
let sub_diag = if negated_token.is_numeric_lit() {
@ -672,7 +677,6 @@ impl<'a> Parser<'a> {
),
});
// ...and recover!
self.parse_unary_expr(lo, UnOp::Not)
}
@ -1593,7 +1597,7 @@ impl<'a> Parser<'a> {
vis.0
};
// Suggestion involves adding a (as of time of writing this, unstable) labeled block.
// Suggestion involves adding a labeled block.
//
// If there are no breaks that may use this label, suggest removing the label and
// recover to the unmodified expression.

View File

@ -164,7 +164,10 @@ impl<'a> Parser<'a> {
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
this.parse_assoc_expr_with(
0,
LhsExpr::AlreadyParsed { expr, starts_statement: true },
)
})?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else {
@ -198,7 +201,10 @@ impl<'a> Parser<'a> {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
let e = self.parse_assoc_expr_with(
0,
LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
)?;
StmtKind::Expr(e)
};
Ok(self.mk_stmt(lo.to(hi), kind))

View File

@ -374,6 +374,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
})
}
}
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn report_fulfillment_errors(
&self,
@ -852,6 +853,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut suggested =
self.suggest_dereferences(&obligation, &mut err, trait_predicate);
suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref;
if let (ty::FnPtr(_), ty::FnDef(..)) =
(cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
{
err.span_suggestion(
span.shrink_to_hi(),
format!(
"the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
cand.print_only_trait_path(),
cand.self_ty(),
),
format!(" as {}", cand.self_ty()),
Applicability::MaybeIncorrect,
);
true
} else {
false
}
} else {
false
} || suggested;
suggested |=
self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
suggested |= self.suggest_semicolon_removal(
@ -1968,27 +1992,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
candidates.sort();
candidates.dedup();
let len = candidates.len();
if candidates.len() == 0 {
if candidates.is_empty() {
return false;
}
if candidates.len() == 1 {
let ty_desc = match candidates[0].self_ty().kind() {
ty::FnPtr(_) => Some("fn pointer"),
_ => None,
};
let the_desc = match ty_desc {
Some(desc) => format!(" implemented for {} `", desc),
None => " implemented for `".to_string(),
};
if let &[cand] = &candidates[..] {
let (desc, mention_castable) =
match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
(ty::FnPtr(_), ty::FnDef(..)) => {
(" implemented for fn pointer `", ", cast using `as`")
}
(ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
_ => (" implemented for `", ""),
};
err.highlighted_help(vec![
(
format!("the trait `{}` ", candidates[0].print_only_trait_path()),
Style::NoStyle,
),
(format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
("is".to_string(), Style::Highlight),
(the_desc, Style::NoStyle),
(candidates[0].self_ty().to_string(), Style::Highlight),
(desc.to_string(), Style::NoStyle),
(cand.self_ty().to_string(), Style::Highlight),
("`".to_string(), Style::NoStyle),
(mention_castable.to_string(), Style::NoStyle),
]);
return true;
}

View File

@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin"
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0
git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8
make -j$(nproc) \
CC="$bin/clang" \
NM="$bin/llvm-nm" \

View File

@ -6,6 +6,7 @@ autobins = false
[dependencies]
cargo_metadata = "0.14"
cargo-platform = "0.1.2"
regex = "1"
miropt-test-tools = { path = "../miropt-test-tools" }
lazy_static = "1"

View File

@ -1,7 +1,7 @@
//! Checks the licenses of third-party dependencies.
use cargo_metadata::{Metadata, Package, PackageId, Resolve};
use std::collections::{BTreeSet, HashSet};
use cargo_metadata::{DepKindInfo, Metadata, Package, PackageId};
use std::collections::HashSet;
use std::path::Path;
/// These are licenses that are allowed for all crates, including the runtime,
@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"autocfg",
"bitflags",
"block-buffer",
"bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"cc",
"cfg-if",
"chalk-derive",
"chalk-engine",
"chalk-ir",
"chalk-solve",
"chrono",
"convert_case", // dependency of derive_more
"compiler_builtins",
"cpufeatures",
@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"dlmalloc",
"either",
"ena",
"env_logger",
"expect-test",
"fallible-iterator", // dependency of `thorin`
"fastrand",
"filetime",
"fixedbitset",
"flate2",
"fluent-bundle",
@ -142,13 +138,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"gsgdt",
"hashbrown",
"hermit-abi",
"humantime",
"icu_list",
"icu_locid",
"icu_provider",
"icu_provider_adapters",
"icu_provider_macros",
"if_chain",
"indexmap",
"instant",
"intl-memoizer",
@ -156,7 +150,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"itertools",
"itoa",
"jobserver",
"js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"lazy_static",
"libc",
"libloading",
@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"memmap2",
"memoffset",
"miniz_oxide",
"num-integer",
"num-traits",
"num_cpus",
"object",
"odht",
@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"proc-macro2",
"psm",
"punycode",
"quick-error",
"quote",
"rand",
"rand_chacha",
@ -235,7 +225,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"thiserror-impl",
"thorin-dwp",
"thread_local",
"time",
"tinystr",
"tinyvec",
"tinyvec_macros",
@ -268,13 +257,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"valuable",
"version_check",
"wasi",
// vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"wasm-bindgen",
"wasm-bindgen-backend",
"wasm-bindgen-macro",
"wasm-bindgen-macro-support",
"wasm-bindgen-shared",
// ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"winapi",
"winapi-i686-pc-windows-gnu",
"winapi-util",
@ -485,75 +467,57 @@ fn check_permitted_dependencies(
restricted_dependency_crates: &[&'static str],
bad: &mut bool,
) {
let mut deps = HashSet::new();
for to_check in restricted_dependency_crates {
let to_check = pkg_from_name(metadata, to_check);
use cargo_platform::Cfg;
use std::str::FromStr;
// We don't expect the compiler to ever run on wasm32, so strip
// out those dependencies to avoid polluting the permitted list.
deps_of_filtered(metadata, &to_check.id, &mut deps, &|dep_kinds| {
dep_kinds.iter().any(|dep_kind| {
dep_kind
.target
.as_ref()
.map(|target| {
!target.matches(
"wasm32-unknown-unknown",
&[
Cfg::from_str("target_arch=\"wasm32\"").unwrap(),
Cfg::from_str("target_os=\"unknown\"").unwrap(),
],
)
})
.unwrap_or(true)
})
});
}
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
for name in permitted_dependencies {
if !metadata.packages.iter().any(|p| p.name == *name) {
for permitted in permitted_dependencies {
if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
tidy_error!(
bad,
"could not find allowed package `{}`\n\
"could not find allowed package `{permitted}`\n\
Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
name
);
}
}
// Get the list in a convenient form.
// Get in a convenient form.
let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
// Check dependencies.
let mut visited = BTreeSet::new();
let mut unapproved = BTreeSet::new();
for &krate in restricted_dependency_crates.iter() {
let pkg = pkg_from_name(metadata, krate);
let mut bad =
check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg);
unapproved.append(&mut bad);
}
if !unapproved.is_empty() {
tidy_error!(bad, "Dependencies for {} not explicitly permitted:", descr);
for dep in unapproved {
println!("* {dep}");
for dep in deps {
let dep = pkg_from_id(metadata, dep);
// If this path is in-tree, we don't require it to be explicitly permitted.
if dep.source.is_some() {
if !permitted_dependencies.contains(dep.name.as_str()) {
tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
}
}
}
}
/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
/// the list of permitted dependencies. Returns a list of disallowed dependencies.
fn check_crate_dependencies<'a>(
permitted_dependencies: &'a HashSet<&'static str>,
metadata: &'a Metadata,
visited: &mut BTreeSet<&'a PackageId>,
krate: &'a Package,
) -> BTreeSet<&'a PackageId> {
// This will contain bad deps.
let mut unapproved = BTreeSet::new();
// Check if we have already visited this crate.
if visited.contains(&krate.id) {
return unapproved;
}
visited.insert(&krate.id);
// If this path is in-tree, we don't require it to be explicitly permitted.
if krate.source.is_some() {
// If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
if !permitted_dependencies.contains(krate.name.as_str()) {
unapproved.insert(&krate.id);
}
}
// Do a DFS in the crate graph.
let to_check = deps_of(metadata, &krate.id);
for dep in to_check {
let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep);
unapproved.append(&mut bad);
}
unapproved
}
/// Prevents multiple versions of some expensive crates.
fn check_crate_duplicate(
metadata: &Metadata,
@ -588,24 +552,6 @@ fn check_crate_duplicate(
}
}
/// Returns a list of dependencies for the given package.
fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
let resolve = metadata.resolve.as_ref().unwrap();
let node = resolve
.nodes
.iter()
.find(|n| &n.id == pkg_id)
.unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
node.deps
.iter()
.map(|dep| {
metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| {
panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id)
})
})
.collect()
}
/// Finds a package with the given name.
fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
let mut i = metadata.packages.iter().filter(|p| p.name == name);
@ -615,41 +561,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package
result
}
fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package {
metadata.packages.iter().find(|p| &p.id == id).unwrap()
}
/// Finds all the packages that are in the rust runtime.
fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
let resolve = metadata.resolve.as_ref().unwrap();
let mut result = HashSet::new();
for name in RUNTIME_CRATES {
let id = &pkg_from_name(metadata, name).id;
normal_deps_of_r(resolve, id, &mut result);
deps_of_filtered(metadata, id, &mut result, &|_| true);
}
result
}
/// Recursively find all normal dependencies.
fn normal_deps_of_r<'a>(
resolve: &'a Resolve,
/// Recursively find all dependencies.
fn deps_of_filtered<'a>(
metadata: &'a Metadata,
pkg_id: &'a PackageId,
result: &mut HashSet<&'a PackageId>,
filter: &dyn Fn(&[DepKindInfo]) -> bool,
) {
if !result.insert(pkg_id) {
return;
}
let node = resolve
let node = metadata
.resolve
.as_ref()
.unwrap()
.nodes
.iter()
.find(|n| &n.id == pkg_id)
.unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
for dep in &node.deps {
normal_deps_of_r(resolve, &dep.pkg, result);
if !filter(&dep.dep_kinds) {
continue;
}
deps_of_filtered(metadata, &dep.pkg, result, filter);
}
}
fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
let resolve = metadata.resolve.as_ref().unwrap();
let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap();
node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect()
}
fn check_rustfix(metadata: &Metadata, bad: &mut bool) {
let cargo = pkg_from_name(metadata, "cargo");
let compiletest = pkg_from_name(metadata, "compiletest");
let cargo_deps = deps_of(metadata, &cargo.id);
let compiletest_deps = deps_of(metadata, &compiletest.id);
let cargo_deps = direct_deps_of(metadata, &cargo.id);
let compiletest_deps = direct_deps_of(metadata, &compiletest.id);
let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap();
let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap();
if cargo_rustfix.version != compiletest_rustfix.version {

View File

@ -18,8 +18,8 @@ fn consts<const C: u32>() {
})
}
static S: i32 = 5;
static mut T: i32 = 10;
static S: i32 = 0x05050505;
static mut T: i32 = 0x0a0a0a0a;
// EMIT_MIR consts.statics.built.after.mir
#[custom_mir(dialect = "built")]
fn statics() {

View File

@ -19,9 +19,9 @@ fn statics() -> () {
}
alloc2 (static: T, size: 4, align: 4) {
0a 00 00 00 ....
0a 0a 0a 0a ....
}
alloc1 (static: S, size: 4, align: 4) {
05 00 00 00 ....
05 05 05 05 ....
}

View File

@ -38,6 +38,6 @@
}
alloc1 (static: STATIC, size: 4, align: 4) {
2a 00 00 00 │ *...
42 42 42 42 │ BBBB
}

View File

@ -1,7 +1,7 @@
// unit-test
// compile-flags: -O
static mut STATIC: u32 = 42;
static mut STATIC: u32 = 0x42424242;
// EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff
fn main() {

View File

@ -26,7 +26,7 @@
_3 = _1; // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52
_2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53
// mir::Constant
// + span: $DIR/issue_75439.rs:7:37: 7:46
// + span: $DIR/issue_75439.rs:8:37: 8:46
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) }
}
@ -49,7 +49,7 @@
_6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35
_5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36
// mir::Constant
// + span: $DIR/issue_75439.rs:10:23: 10:32
// + span: $DIR/issue_75439.rs:11:23: 11:32
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) }
}

View File

@ -1,4 +1,5 @@
// EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff
// ignore-endian-big
use std::mem::transmute;

View File

@ -77,8 +77,6 @@ LL | /// ```
| ^^^
|
= note: error from rustc: unknown start of token: `
= note: error from rustc: unknown start of token: `
= note: error from rustc: unknown start of token: `
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:64:5

View File

@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
LL | type Assoc = T;
| ^ the trait `Copy` is not implemented for `T`
|
note: required for `<T as Complete>::Assoc` to implement `Partial<T>`
--> $DIR/issue-43784-associated-type.rs:1:11
|
LL | pub trait Partial<X: ?Sized>: Copy {
| ^^^^^^^
note: required by a bound in `Complete::Assoc`
--> $DIR/issue-43784-associated-type.rs:5:17
|

View File

@ -6,6 +6,13 @@ LL | Foo(())
| |
| arguments to this struct are incorrect
|
help: the type constructed contains `()` due to the type of the argument passed
--> $DIR/issue-84128.rs:13:9
|
LL | Foo(())
| ^^^^--^
| |
| this argument influences the type of `Foo`
note: tuple struct defined here
--> $DIR/issue-84128.rs:5:8
|

View File

@ -6,6 +6,13 @@ LL | Ok(())
| |
| arguments to this enum variant are incorrect
|
help: the type constructed contains `()` due to the type of the argument passed
--> $DIR/issue-87461.rs:10:5
|
LL | Ok(())
| ^^^--^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
@ -17,6 +24,13 @@ LL | Ok(())
| |
| arguments to this enum variant are incorrect
|
help: the type constructed contains `()` due to the type of the argument passed
--> $DIR/issue-87461.rs:17:5
|
LL | Ok(())
| ^^^--^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
@ -28,6 +42,13 @@ LL | Ok(())
| |
| arguments to this enum variant are incorrect
|
help: the type constructed contains `()` due to the type of the argument passed
--> $DIR/issue-87461.rs:26:9
|
LL | Ok(())
| ^^^--^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL

View File

@ -6,12 +6,15 @@ LL | struct Value(u32);
| |
| doesn't satisfy `Value: Eq`
| doesn't satisfy `Value: Hash`
| doesn't satisfy `Value: PartialEq`
...
LL | hs.insert(Value(0));
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`Value: Eq`
`Value: PartialEq`
which is required by `Value: Eq`
`Value: Hash`
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
|
@ -22,7 +25,10 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
--> $DIR/issue-91550.rs:26:9
|
LL | pub struct NoDerives;
| -------------------- doesn't satisfy `NoDerives: Eq`
| --------------------
| |
| doesn't satisfy `NoDerives: Eq`
| doesn't satisfy `NoDerives: PartialEq`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_eq` not found for this struct
@ -37,6 +43,9 @@ LL | impl<T: Eq> Object<T> {
| ^^ ---------
| |
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialEq`
which is required by `NoDerives: Eq`
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
|
LL | #[derive(Eq, PartialEq)]
@ -46,7 +55,12 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
--> $DIR/issue-91550.rs:27:9
|
LL | pub struct NoDerives;
| -------------------- doesn't satisfy `NoDerives: Ord`
| --------------------
| |
| doesn't satisfy `NoDerives: Eq`
| doesn't satisfy `NoDerives: Ord`
| doesn't satisfy `NoDerives: PartialEq`
| doesn't satisfy `NoDerives: PartialOrd`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_ord` not found for this struct
@ -61,6 +75,13 @@ LL | impl<T: Ord> Object<T> {
| ^^^ ---------
| |
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialOrd`
which is required by `NoDerives: Ord`
`NoDerives: PartialEq`
which is required by `NoDerives: Ord`
`NoDerives: Eq`
which is required by `NoDerives: Ord`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
@ -72,7 +93,9 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
LL | pub struct NoDerives;
| --------------------
| |
| doesn't satisfy `NoDerives: Eq`
| doesn't satisfy `NoDerives: Ord`
| doesn't satisfy `NoDerives: PartialEq`
| doesn't satisfy `NoDerives: PartialOrd`
LL |
LL | struct Object<T>(T);
@ -91,6 +114,13 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialEq`
which is required by `NoDerives: Ord`
`NoDerives: Eq`
which is required by `NoDerives: Ord`
`NoDerives: PartialEq`
which is required by `NoDerives: PartialOrd`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]

View File

@ -17,6 +17,7 @@ LL | type Copy<T>: Copy = Box<T>;
| ^^^^^^ the trait `Clone` is not implemented for `T`
|
= note: required for `Box<T>` to implement `Clone`
= note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy`
note: required by a bound in `UnsafeCopy::Copy`
--> $DIR/issue-74824.rs:6:19
|

View File

@ -23,6 +23,13 @@ LL | A(self.0 + rhs.0)
|
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
--> $DIR/missing-bounds.rs:11:9
|
LL | A(self.0 + rhs.0)
| ^^--------------^
| |
| this argument influences the type of `A`
note: tuple struct defined here
--> $DIR/missing-bounds.rs:5:8
|

View File

@ -11,6 +11,13 @@ LL | Some(true)
|
= note: expected type parameter `bool` (type parameter `bool`)
found type `bool` (`bool`)
help: the type constructed contains `bool` due to the type of the argument passed
--> $DIR/issue-35030.rs:9:9
|
LL | Some(true)
| ^^^^^----^
| |
| this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL

View File

@ -6,6 +6,8 @@ LL | this.is_subset(other)
|
= note: the following trait bounds were not satisfied:
`T: Eq`
`T: PartialEq`
which is required by `T: Eq`
`T: Hash`
help: consider restricting the type parameters to satisfy the trait bounds
|

View File

@ -2,4 +2,8 @@ fn main() {
let y = 0;
//~^ ERROR unknown start of token: \u{37e}
//~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
    let x = 0;
//~^ ERROR unknown start of token: \u{a0}
//~^^ NOTE character appears 3 more times
//~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
}

View File

@ -9,5 +9,17 @@ help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), b
LL | let y = 0;
| ~
error: aborting due to previous error
error: unknown start of token: \u{a0}
--> $DIR/unicode-chars.rs:5:5
|
LL |     let x = 0;
| ^^^^
|
= note: character appears 3 more times
help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
|
LL | let x = 0;
| ++++
error: aborting due to 2 previous errors

View File

@ -11,6 +11,13 @@ LL | let _: Option<(i32, bool)> = Some(1, 2);
| ^
= note: expected tuple `(i32, bool)`
found type `{integer}`
help: the type constructed contains `{integer}` due to the type of the argument passed
--> $DIR/args-instead-of-tuple-errors.rs:6:34
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
| ^^^^^-^^^^
| |
| this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: remove the extra argument
@ -64,6 +71,13 @@ LL | let _: Option<(i32,)> = Some(5_usize);
|
= note: expected tuple `(i32,)`
found type `usize`
help: the type constructed contains `usize` due to the type of the argument passed
--> $DIR/args-instead-of-tuple-errors.rs:14:29
|
LL | let _: Option<(i32,)> = Some(5_usize);
| ^^^^^-------^
| |
| this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
@ -77,6 +91,13 @@ LL | let _: Option<(i32,)> = Some((5_usize));
|
= note: expected tuple `(i32,)`
found type `usize`
help: the type constructed contains `usize` due to the type of the argument passed
--> $DIR/args-instead-of-tuple-errors.rs:17:29
|
LL | let _: Option<(i32,)> = Some((5_usize));
| ^^^^^---------^
| |
| this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL

View File

@ -8,6 +8,13 @@ LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
|
= note: expected reference `&str`
found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed
--> $DIR/sugg-else-for-closure.rs:6:14
|
LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
| ^^^^^^^^^^^^-------------------------------^
| |
| this argument influences the return type of `unwrap_or`
note: associated function defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: try calling `unwrap_or_else` instead

View File

@ -0,0 +1,26 @@
// There are two different instances to check that even if
// the trait is implemented for the output of a function,
// it will still be displayed if the function itself implements a trait.
trait Foo {}
impl Foo for fn() -> bool {}
impl Foo for bool {}
fn example() -> bool {
true
}
trait NoOtherFoo {}
impl NoOtherFoo for fn() -> bool {}
fn do_on_foo(v: impl Foo) {}
fn do_on_single_foo(v: impl NoOtherFoo) {}
fn main() {
do_on_foo(example);
//~^ ERROR the trait bound
do_on_single_foo(example);
//~^ ERROR the trait bound
}

View File

@ -0,0 +1,43 @@
error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied
--> $DIR/fn-trait-cast-diagnostic.rs:21:15
|
LL | do_on_foo(example);
| --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}`
| |
| required by a bound introduced by this call
|
note: required by a bound in `do_on_foo`
--> $DIR/fn-trait-cast-diagnostic.rs:17:22
|
LL | fn do_on_foo(v: impl Foo) {}
| ^^^ required by this bound in `do_on_foo`
help: use parentheses to call this function
|
LL | do_on_foo(example());
| ++
help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
|
LL | do_on_foo(example as fn() -> bool);
| +++++++++++++++
error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied
--> $DIR/fn-trait-cast-diagnostic.rs:24:22
|
LL | do_on_single_foo(example);
| ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}`
| |
| required by a bound introduced by this call
|
note: required by a bound in `do_on_single_foo`
--> $DIR/fn-trait-cast-diagnostic.rs:18:29
|
LL | fn do_on_single_foo(v: impl NoOtherFoo) {}
| ^^^^^^^^^^ required by this bound in `do_on_single_foo`
help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
|
LL | do_on_single_foo(example as fn() -> bool);
| +++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
LL | impl<T> Complete for T {}
| ^ the trait `Copy` is not implemented for `T`
|
note: required for `T` to implement `Partial`
--> $DIR/issue-43784-supertrait.rs:1:11
|
LL | pub trait Partial: Copy {
| ^^^^^^^
note: required by a bound in `Complete`
--> $DIR/issue-43784-supertrait.rs:4:21
|

View File

@ -11,6 +11,13 @@ LL | builder.push(output);
|
= note: expected type parameter `F`
found struct `Class<P>`
help: the return type of this call is `Class<P>` due to the type of the argument passed
--> $DIR/issue-52893.rs:53:9
|
LL | builder.push(output);
| ^^^^^^^^^^^^^------^
| |
| this argument influences the return type of `push`
note: associated function defined here
--> $DIR/issue-52893.rs:11:8
|

View File

@ -6,12 +6,15 @@ LL | takes(function);
| |
| required by a bound introduced by this call
|
= help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
note: required by a bound in `takes`
--> $DIR/issue-99875.rs:9:18
|
LL | fn takes(_: impl Trait) {}
| ^^^^^ required by this bound in `takes`
help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as`
|
LL | takes(function as fn(Argument) -> Return);
| +++++++++++++++++++++++++
error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
--> $DIR/issue-99875.rs:14:11

View File

@ -0,0 +1,88 @@
// These are simplifications of the tower traits by the same name:
pub trait Service<Request> {
type Response;
}
pub trait Layer<C> {
type Service;
}
// Any type will do here:
pub struct Req;
pub struct Res;
// This is encoding a trait alias.
pub trait ParticularService:
Service<Req, Response = Res> {
}
impl<T> ParticularService for T
where
T: Service<Req, Response = Res>,
{
}
// This is also a trait alias.
// The weird = <Self as ...> bound is there so that users of the trait do not
// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671
// for context, and in particular the workaround in:
// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828
pub trait ParticularServiceLayer<C>:
Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
{
type Service: ParticularService;
}
impl<T, C> ParticularServiceLayer<C> for T
where
T: Layer<C>,
T::Service: ParticularService,
{
type Service = T::Service;
}
// These are types that implement the traits that the trait aliases refer to.
// They should also implement the alias traits due to the blanket impls.
struct ALayer<C>(C);
impl<C> Layer<C> for ALayer<C> {
type Service = AService;
}
struct AService;
impl Service<Req> for AService {
// However, AService does _not_ meet the blanket implementation,
// since its Response type is bool, not Res as it should be.
type Response = bool;
}
// This is a wrapper type around ALayer that uses the trait alias
// as a way to communicate the requirements of the provided types.
struct Client<C>(C);
// The method and the free-standing function below both have the same bounds.
impl<C> Client<C>
where
ALayer<C>: ParticularServiceLayer<C>,
{
fn check(&self) {}
}
fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
// But, they give very different error messages.
fn main() {
// This gives a very poor error message that does nothing to point the user
// at the underlying cause of why the types involved do not meet the bounds.
Client(()).check(); //~ ERROR E0599
// This gives a good(ish) error message that points the user at _why_ the
// bound isn't met, and thus how they might fix it.
check(()); //~ ERROR E0271
}

View File

@ -0,0 +1,76 @@
error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied
--> $DIR/track-obligations.rs:83:16
|
LL | struct ALayer<C>(C);
| ----------------
| |
| doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service`
| doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
...
LL | struct Client<C>(C);
| ---------------- method `check` not found for this struct
...
LL | Client(()).check();
| ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
|
note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
--> $DIR/track-obligations.rs:35:14
|
LL | pub trait ParticularServiceLayer<C>:
| ----------------------
LL | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
--> $DIR/track-obligations.rs:71:16
|
LL | impl<C> Client<C>
| ---------
LL | where
LL | ALayer<C>: ParticularServiceLayer<C>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the trait `ParticularServiceLayer` must be implemented
--> $DIR/track-obligations.rs:34:1
|
LL | / pub trait ParticularServiceLayer<C>:
LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
| |____________________________________________________________________^
error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
--> $DIR/track-obligations.rs:87:11
|
LL | check(());
| ----- ^^ type mismatch resolving `<AService as Service<Req>>::Response == Res`
| |
| required by a bound introduced by this call
|
note: expected this to be `Res`
--> $DIR/track-obligations.rs:60:21
|
LL | type Response = bool;
| ^^^^
note: required for `AService` to implement `ParticularService`
--> $DIR/track-obligations.rs:22:9
|
LL | impl<T> ParticularService for T
| ^^^^^^^^^^^^^^^^^ ^
LL | where
LL | T: Service<Req, Response = Res>,
| -------------- unsatisfied trait bound introduced here
note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>`
--> $DIR/track-obligations.rs:40:12
|
LL | impl<T, C> ParticularServiceLayer<C> for T
| ^^^^^^^^^^^^^^^^^^^^^^^^^ ^
...
LL | T::Service: ParticularService,
| ----------------- unsatisfied trait bound introduced here
note: required by a bound in `check`
--> $DIR/track-obligations.rs:76:36
|
LL | fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0271, E0599.
For more information about an error, try `rustc --explain E0271`.

View File

@ -0,0 +1,28 @@
fn function<T>(x: T, y: bool) -> T {
x
}
struct S {}
impl S {
fn method<T>(&self, x: T) -> T {
x
}
}
fn wrong_arg_type(x: u32) -> u32 {
x
}
fn main() {
// Should not trigger.
let x = wrong_arg_type(0u16); //~ ERROR mismatched types
let x: u16 = function(0, 0u8); //~ ERROR mismatched types
// Should trigger exactly once for the first argument.
let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect
// Should trigger.
let x: u16 = function(0u32, true); //~ ERROR mismatched types
let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types
function(0u32, 8u8) //~ ERROR arguments to this function are incorrect
}

View File

@ -0,0 +1,131 @@
error[E0308]: mismatched types
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28
|
LL | let x = wrong_arg_type(0u16);
| -------------- ^^^^ expected `u32`, found `u16`
| |
| arguments to this function are incorrect
|
note: function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4
|
LL | fn wrong_arg_type(x: u32) -> u32 {
| ^^^^^^^^^^^^^^ ------
help: change the type of the numeric literal from `u16` to `u32`
|
LL | let x = wrong_arg_type(0u32);
| ~~~
error[E0308]: mismatched types
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30
|
LL | let x: u16 = function(0, 0u8);
| -------- ^^^ expected `bool`, found `u8`
| |
| arguments to this function are incorrect
|
note: function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
|
LL | fn function<T>(x: T, y: bool) -> T {
| ^^^^^^^^ -------
error[E0308]: arguments to this function are incorrect
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
|
LL | let x: u16 = function(0u32, 0u8);
| ^^^^^^^^ ---- --- expected `bool`, found `u8`
| |
| expected `u16`, found `u32`
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
|
LL | let x: u16 = function(0u32, 0u8);
| ^^^^^^^^^----^^^^^^
| |
| this argument influences the return type of `function`
note: function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
|
LL | fn function<T>(x: T, y: bool) -> T {
| ^^^^^^^^ ---- -------
help: change the type of the numeric literal from `u32` to `u16`
|
LL | let x: u16 = function(0u16, 0u8);
| ~~~
error[E0308]: mismatched types
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27
|
LL | let x: u16 = function(0u32, true);
| -------- ^^^^ expected `u16`, found `u32`
| |
| arguments to this function are incorrect
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18
|
LL | let x: u16 = function(0u32, true);
| ^^^^^^^^^----^^^^^^^
| |
| this argument influences the return type of `function`
note: function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
|
LL | fn function<T>(x: T, y: bool) -> T {
| ^^^^^^^^ ----
help: change the type of the numeric literal from `u32` to `u16`
|
LL | let x: u16 = function(0u16, true);
| ~~~
error[E0308]: mismatched types
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32
|
LL | let x: u16 = (S {}).method(0u32);
| ------ ^^^^ expected `u16`, found `u32`
| |
| arguments to this method are incorrect
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18
|
LL | let x: u16 = (S {}).method(0u32);
| ^^^^^^^^^^^^^^----^
| |
| this argument influences the return type of `method`
note: associated function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8
|
LL | fn method<T>(&self, x: T) -> T {
| ^^^^^^ ----
help: change the type of the numeric literal from `u32` to `u16`
|
LL | let x: u16 = (S {}).method(0u16);
| ~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
|
LL | function(0u32, 8u8)
| ^^^^^^^^ ---- --- expected `bool`, found `u8`
| |
| expected `()`, found `u32`
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
|
LL | function(0u32, 8u8)
| ^^^^^^^^^----^^^^^^
| |
| this argument influences the return type of `function`
note: function defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
|
LL | fn function<T>(x: T, y: bool) -> T {
| ^^^^^^^^ ---- -------
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -8,6 +8,13 @@ LL | fn main() { test(Ok(())); }
|
= note: expected enum `Option<()>`
found unit type `()`
help: the type constructed contains `()` due to the type of the argument passed
--> $DIR/issue-46112.rs:9:18
|
LL | fn main() { test(Ok(())); }
| ^^^--^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
help: try wrapping the expression in `Some`

View File

@ -14,6 +14,13 @@ LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
|
= note: expected tuple `(&mut u8,)`
found type `{integer}`
help: the return type of this call is `{integer}` due to the type of the argument passed
--> $DIR/issue-84768.rs:7:5
|
LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
| |
| this argument influences the return type of `FnOnce`
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL

View File

@ -21,6 +21,13 @@ LL | <i32 as Add<i32>>::add(1u32, 2);
| |
| arguments to this function are incorrect
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/ufcs-qpath-self-mismatch.rs:7:5
|
LL | <i32 as Add<i32>>::add(1u32, 2);
| ^^^^^^^^^^^^^^^^^^^^^^^----^^^^
| |
| this argument influences the return type of `Add`
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
@ -36,6 +43,13 @@ LL | <i32 as Add<i32>>::add(1, 2u32);
| |
| arguments to this function are incorrect
|
help: the return type of this call is `u32` due to the type of the argument passed
--> $DIR/ufcs-qpath-self-mismatch.rs:9:5
|
LL | <i32 as Add<i32>>::add(1, 2u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^----^
| |
| this argument influences the return type of `Add`
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`

View File

@ -251,7 +251,7 @@ new_pr = true
[autolabel."WG-trait-system-refactor"]
trigger_files = [
"compiler/rustc_trait_selection/solve"
"compiler/rustc_trait_selection/src/solve"
]
[notify-zulip."I-prioritize"]