1
Fork 0

Auto merge of #112957 - matthiaskrgr:rollup-7ly0nv7, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #111747 (Don't structurally resolve during method ambiguity in probe)
 - #112704 (slice::from_raw_parts: mention no-wrap-around condition)
 - #112927 (Fix indentation for where clause in rustdoc pages)
 - #112933 (Avoid `&format` in error message code)
 - #112935 (style-guide: Fix typo)
 - #112941 (typo)
 - #112942 (style-guide: Organizational and editing tweaks (no semantic changes))
 - #112944 (style-guide: Add language disclaiming any effects on non-default Rust styles)
 - #112948 (Avoid guessing unknown trait implementation in suggestions)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-23 11:41:43 +00:00
commit 54d6738a8d
29 changed files with 242 additions and 116 deletions

View file

@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
move_from_span: Span, move_from_span: Span,
move_from_desc: &str, move_from_desc: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,) struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
} }
/// Signal an error due to an attempt to move out of the interior /// Signal an error due to an attempt to move out of the interior

View file

@ -12,6 +12,7 @@ use rustc_hir::def::DefKind;
use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
use rustc_middle::middle::stability; use rustc_middle::middle::stability;
@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
} }
} else { } else {
// Encountered a real ambiguity, so abort the lookup. If `ty` is not // Ended up encountering a type variable when doing autoderef,
// an `Err`, report the right "type annotations needed" error pointing // but it may not be a type variable after processing obligations
// to it. // in our local `FnCtxt`, so don't call `structurally_resolved_type`.
let ty = &bad_ty.ty; let ty = &bad_ty.ty;
let ty = self let ty = self
.probe_instantiate_query_response(span, &orig_values, ty) .probe_instantiate_query_response(span, &orig_values, ty)
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
let ty = self.structurally_resolved_type(span, ty.value); let ty = self.resolve_vars_if_possible(ty.value);
assert!(matches!(ty.kind(), ty::Error(_))); let guar = match *ty.kind() {
ty::Infer(ty::TyVar(_)) => self
.err_ctxt()
.emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true)
.emit(),
ty::Error(guar) => guar,
_ => bug!("unexpected bad final type in method autoderef"),
};
self.demand_eqtype(span, ty, self.tcx.ty_error(guar));
return Err(MethodError::NoMatch(NoMatchData { return Err(MethodError::NoMatch(NoMatchData {
static_candidates: Vec::new(), static_candidates: Vec::new(),
unsatisfied_predicates: Vec::new(), unsatisfied_predicates: Vec::new(),

View file

@ -54,7 +54,7 @@ fn path_to_string(path: &syn::Path) -> String {
/// Returns an error diagnostic on span `span` with msg `msg`. /// Returns an error diagnostic on span `span` with msg `msg`.
#[must_use] #[must_use]
pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { pub(crate) fn span_err<T: Into<String>>(span: impl MultiSpan, msg: T) -> Diagnostic {
Diagnostic::spanned(span, Level::Error, msg) Diagnostic::spanned(span, Level::Error, msg)
} }
@ -77,11 +77,9 @@ pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic {
let span = attr.span().unwrap(); let span = attr.span().unwrap();
let path = path_to_string(attr.path()); let path = path_to_string(attr.path());
match attr.meta { match attr.meta {
Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")), Meta::Path(_) => span_err(span, format!("`#[{path}]` is not a valid attribute")),
Meta::NameValue(_) => { Meta::NameValue(_) => span_err(span, format!("`#[{path} = ...]` is not a valid attribute")),
span_err(span, &format!("`#[{path} = ...]` is not a valid attribute")) Meta::List(_) => span_err(span, format!("`#[{path}(...)]` is not a valid attribute")),
}
Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")),
} }
} }

View file

@ -200,7 +200,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
throw_span_err!( throw_span_err!(
attr.span().unwrap(), attr.span().unwrap(),
&format!( format!(
"diagnostic slug must be first argument of a `#[{name}(...)]` attribute" "diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
) )
); );

View file

@ -347,7 +347,7 @@ pub(crate) trait HasFieldMap {
None => { None => {
span_err( span_err(
span.unwrap(), span.unwrap(),
&format!("`{field}` doesn't refer to a field on this type"), format!("`{field}` doesn't refer to a field on this type"),
) )
.emit(); .emit();
quote! { quote! {

View file

@ -2382,17 +2382,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&& let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
{ {
let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count(); let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
let message = if non_blanket_impl_count == 1 { // If there is only one implementation of the trait, suggest using it.
"use the fully-qualified path to the only available implementation".to_string() // Otherwise, use a placeholder comment for the implementation.
} else { let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
"use the fully-qualified path to the only available implementation".to_string(),
format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
)} else {(
format!( format!(
"use a fully-qualified path to a specific available implementation ({} found)", "use a fully-qualified path to a specific available implementation ({} found)",
non_blanket_impl_count non_blanket_impl_count
) ),
}; "</* self type */ as ".to_string()
)};
let mut suggestions = vec![( let mut suggestions = vec![(
path.span.shrink_to_lo(), path.span.shrink_to_lo(),
format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity()) impl_suggestion
)]; )];
if let Some(generic_arg) = trait_path_segment.args { if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext); let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);

View file

@ -32,7 +32,8 @@ use crate::ptr;
/// * The memory referenced by the returned slice must not be mutated for the duration /// * The memory referenced by the returned slice must not be mutated for the duration
/// of lifetime `'a`, except inside an `UnsafeCell`. /// of lifetime `'a`, except inside an `UnsafeCell`.
/// ///
/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`. /// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`,
/// and adding that size to `data` must not "wrap around" the address space.
/// See the safety documentation of [`pointer::offset`]. /// See the safety documentation of [`pointer::offset`].
/// ///
/// # Caveat /// # Caveat
@ -125,7 +126,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
/// (not derived from the return value) for the duration of lifetime `'a`. /// (not derived from the return value) for the duration of lifetime `'a`.
/// Both read and write accesses are forbidden. /// Both read and write accesses are forbidden.
/// ///
/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`. /// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`,
/// and adding that size to `data` must not "wrap around" the address space.
/// See the safety documentation of [`pointer::offset`]. /// See the safety documentation of [`pointer::offset`].
/// ///
/// [valid]: ptr#safety /// [valid]: ptr#safety
@ -179,15 +181,16 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
/// the last element, such that the offset from the end to the start pointer is /// the last element, such that the offset from the end to the start pointer is
/// the length of the slice. /// the length of the slice.
/// ///
/// * The range must contain `N` consecutive properly initialized values of type `T`:
///
/// * The entire memory range of this slice must be contained within a single allocated object! /// * The entire memory range of this slice must be contained within a single allocated object!
/// Slices can never span across multiple allocated objects. /// Slices can never span across multiple allocated objects.
/// ///
/// * The range must contain `N` consecutive properly initialized values of type `T`.
///
/// * The memory referenced by the returned slice must not be mutated for the duration /// * The memory referenced by the returned slice must not be mutated for the duration
/// of lifetime `'a`, except inside an `UnsafeCell`. /// of lifetime `'a`, except inside an `UnsafeCell`.
/// ///
/// * The total length of the range must be no larger than `isize::MAX`. /// * The total length of the range must be no larger than `isize::MAX`,
/// and adding that size to `data` must not "wrap around" the address space.
/// See the safety documentation of [`pointer::offset`]. /// See the safety documentation of [`pointer::offset`].
/// ///
/// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements. /// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements.
@ -247,16 +250,17 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
/// the last element, such that the offset from the end to the start pointer is /// the last element, such that the offset from the end to the start pointer is
/// the length of the slice. /// the length of the slice.
/// ///
/// * The range must contain `N` consecutive properly initialized values of type `T`:
///
/// * The entire memory range of this slice must be contained within a single allocated object! /// * The entire memory range of this slice must be contained within a single allocated object!
/// Slices can never span across multiple allocated objects. /// Slices can never span across multiple allocated objects.
/// ///
/// * The range must contain `N` consecutive properly initialized values of type `T`.
///
/// * The memory referenced by the returned slice must not be accessed through any other pointer /// * The memory referenced by the returned slice must not be accessed through any other pointer
/// (not derived from the return value) for the duration of lifetime `'a`. /// (not derived from the return value) for the duration of lifetime `'a`.
/// Both read and write accesses are forbidden. /// Both read and write accesses are forbidden.
/// ///
/// * The total length of the range must be no larger than `isize::MAX`. /// * The total length of the range must be no larger than `isize::MAX`,
/// and adding that size to `data` must not "wrap around" the address space.
/// See the safety documentation of [`pointer::offset`]. /// See the safety documentation of [`pointer::offset`].
/// ///
/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements. /// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements.

View file

@ -16,9 +16,21 @@ Rust code has similar formatting, less mental effort is required to comprehend a
new project, lowering the barrier to entry for new developers. new project, lowering the barrier to entry for new developers.
Thus, there are productivity benefits to using a formatting tool (such as Thus, there are productivity benefits to using a formatting tool (such as
rustfmt), and even larger benefits by using a community-consistent formatting, `rustfmt`), and even larger benefits by using a community-consistent
typically by using a formatting tool's default settings. formatting, typically by using a formatting tool's default settings.
## The default Rust style
The Rust Style Guide defines the default Rust style, and *recommends* that
developers and tools follow the default Rust style. Tools such as `rustfmt` use
the style guide as a reference for the default style. Everything in this style
guide, whether or not it uses language such as "must" or the imperative mood
such as "insert a space ..." or "break the line after ...", refers to the
default style.
This should not be interpreted as forbidding developers from following a
non-default style, or forbidding tools from adding any particular configuration
options.
## Formatting conventions ## Formatting conventions
@ -28,8 +40,47 @@ typically by using a formatting tool's default settings.
* Each level of indentation must be four spaces (that is, all indentation * Each level of indentation must be four spaces (that is, all indentation
outside of string literals and comments must be a multiple of four). outside of string literals and comments must be a multiple of four).
* The maximum width for a line is 100 characters. * The maximum width for a line is 100 characters.
* A tool should be configurable for all three of these variables. * A tool may choose to make some of these configurable.
#### Block indent
Prefer block indent over visual indent:
```rust
// Block indent
a_function_call(
foo,
bar,
);
// Visual indent
a_function_call(foo,
bar);
```
This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
example) and less rightward drift.
### Trailing commas
Lists should have a trailing comma when followed by a newline:
```rust
function_call(
argument,
another_argument,
);
let array = [
element,
another_element,
yet_another_element,
];
```
This makes moving code (e.g., by copy and paste) easier, and makes diffs
smaller, as appending or removing items does not require modifying another line
to add or remove a comma.
### Blank lines ### Blank lines
@ -48,11 +99,7 @@ fn bar() {}
fn baz() {} fn baz() {}
``` ```
Formatting tools should make the bounds on blank lines configurable: there Formatting tools may wish to make the bounds on blank lines configurable.
should be separate minimum and maximum numbers of newlines between both
statements and (top-level) items (i.e., four options). As described above, the
defaults for both statements and items should be minimum: 1, maximum: 2.
### [Module-level items](items.md) ### [Module-level items](items.md)
### [Statements](statements.md) ### [Statements](statements.md)

View file

@ -2,10 +2,10 @@
[Introduction](README.md) [Introduction](README.md)
- [Module-level items](items.md) - [Items](items.md)
- [Statements](statements.md) - [Statements](statements.md)
- [Expressions](expressions.md) - [Expressions](expressions.md)
- [Types](types.md) - [Types and Bounds](types.md)
- [Non-formatting conventions](advice.md) - [Other style advice](advice.md)
- [`Cargo.toml` conventions](cargo.md) - [`Cargo.toml` conventions](cargo.md)
- [Principles used for deciding these guidelines](principles.md) - [Guiding principles and rationale](principles.md)

View file

@ -25,9 +25,9 @@ if y {
* Local variables shall be `snake_case`, * Local variables shall be `snake_case`,
* Macro names shall be `snake_case`, * Macro names shall be `snake_case`,
* Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`.
* When a name is forbidden because it is a reserved word (e.g., `crate`), use a * When a name is forbidden because it is a reserved word (such as `crate`),
trailing underscore to make the name legal (e.g., `crate_`), or use raw either use a raw identifier (`r#crate`) or use a trailing underscore
identifiers if possible. (`crate_`). Don't misspell the word (`krate`).
### Modules ### Modules

View file

@ -1,4 +1,4 @@
# Cargo.toml conventions # `Cargo.toml` conventions
## Formatting conventions ## Formatting conventions
@ -25,16 +25,17 @@ not indent any key names; start all key names at the start of a line.
Use multi-line strings (rather than newline escape sequences) for any string Use multi-line strings (rather than newline escape sequences) for any string
values that include multiple lines, such as the crate description. values that include multiple lines, such as the crate description.
For array values, such as a list of authors, put the entire list on the same For array values, such as a list of features, put the entire list on the same
line as the key, if it fits. Otherwise, use block indentation: put a newline line as the key, if it fits. Otherwise, use block indentation: put a newline
after the opening square bracket, indent each item by one indentation level, after the opening square bracket, indent each item by one indentation level,
put a comma after each item (including the last), and put the closing square put a comma after each item (including the last), and put the closing square
bracket at the start of a line by itself after the last item. bracket at the start of a line by itself after the last item.
```rust ```rust
authors = [ some_feature = [
"A Uthor <a.uthor@example.org>", "another_feature",
"Another Author <author@example.net>", "yet_another_feature",
"some_dependency?/some_feature",
] ]
``` ```
@ -54,11 +55,11 @@ version = "4.5.6"
## Metadata conventions ## Metadata conventions
The authors list should consist of strings that each contain an author name The authors list, if present, should consist of strings that each contain an
followed by an email address in angle brackets: `Full Name <email@address>`. author name followed by an email address in angle brackets: `Full Name
It should not contain bare email addresses, or names without email addresses. <email@address>`. It should not contain bare email addresses, or names without
(The authors list may also include a mailing list address without an associated email addresses. (The authors list may also include a mailing list address
name.) without an associated name.)
The license field must contain a valid [SPDX The license field must contain a valid [SPDX
expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60), expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),

View file

@ -690,7 +690,7 @@ Where it is possible to use a block form on the right-hand side and avoid
breaking the left-hand side, do that. E.g. breaking the left-hand side, do that. E.g.
```rust ```rust
// Assuming the following line does done fit in the max width // Assuming the following line does not fit in the max width
a_very_long_pattern | another_pattern => ALongStructName { a_very_long_pattern | another_pattern => ALongStructName {
... ...
}, },

View file

@ -1,5 +1,10 @@
## Items ## Items
Items consist of the set of things permitted at the top level of a module.
However, Rust also allows some items to appear within some other types of
items, such as within a function. The same formatting conventions apply whether
an item appears at module level or within another item.
`extern crate` statements must be first in a file. They must be ordered `extern crate` statements must be first in a file. They must be ordered
alphabetically. alphabetically.
@ -15,8 +20,8 @@ Tools should make the above ordering optional.
### Function definitions ### Function definitions
In Rust, one finds functions by searching for `fn [function-name]`; It's In Rust, people often find functions by searching for `fn [function-name]`, so
important that you style your code so that it's very searchable in this way. the formatting of function definitions shold enable this.
The proper ordering and spacing is: The proper ordering and spacing is:
@ -63,8 +68,9 @@ let y = (11, 22, 33);
In the declaration, put each variant on its own line, block indented. In the declaration, put each variant on its own line, block indented.
Format each variant accordingly as either a struct, tuple struct, or identifier, Format each variant accordingly as either a struct (but without the `struct`
which doesn't require special formatting (but without the `struct` keyword. keyword), a tuple struct, or an identifier (which doesn't require special
formatting):
```rust ```rust
enum FooBar { enum FooBar {
@ -139,7 +145,7 @@ union Foo {
Put the whole struct on one line if possible. Types in the parentheses should be Put the whole struct on one line if possible. Types in the parentheses should be
separated by a comma and space with no trailing comma. No spaces around the separated by a comma and space with no trailing comma. No spaces around the
parentheses or semi-colon: parentheses or semicolon:
```rust ```rust
pub struct Foo(String, u8); pub struct Foo(String, u8);
@ -230,7 +236,7 @@ impl Bar
`extern crate foo;` `extern crate foo;`
Use spaces around keywords, no spaces around the semi-colon. Use spaces around keywords, no spaces around the semicolon.
### Modules ### Modules
@ -245,7 +251,7 @@ mod foo;
``` ```
Use spaces around keywords and before the opening brace, no spaces around the Use spaces around keywords and before the opening brace, no spaces around the
semi-colon. semicolon.
### macro\_rules! ### macro\_rules!
@ -478,8 +484,8 @@ foo::{
A *group* of imports is a set of imports on the same or sequential lines. One or A *group* of imports is a set of imports on the same or sequential lines. One or
more blank lines or other items (e.g., a function) separate groups of imports. more blank lines or other items (e.g., a function) separate groups of imports.
Within a group of imports, imports must be sorted ascii-betically. Groups of Within a group of imports, imports must be sorted ASCIIbetically (uppercase
imports must not be merged or re-ordered. before lowercase). Groups of imports must not be merged or re-ordered.
E.g., input: E.g., input:
@ -505,13 +511,9 @@ use b;
Because of `macro_use`, attributes must also start a new group and prevent Because of `macro_use`, attributes must also start a new group and prevent
re-ordering. re-ordering.
Note that tools which only have access to syntax (such as Rustfmt) cannot tell
which imports are from an external crate or the std lib, etc.
#### Ordering list import #### Ordering list import
Names in a list import must be sorted ascii-betically, but with `self` and Names in a list import must be sorted ASCIIbetically, but with `self` and
`super` first, and groups and glob imports last. This applies recursively. For `super` first, and groups and glob imports last. This applies recursively. For
example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g., example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
`use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`. `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`.

View file

@ -1,7 +1,7 @@
# Guiding principles and rationale # Guiding principles and rationale
When deciding on style guidelines, the style team tried to be guided by the When deciding on style guidelines, the style team follows these guiding
following principles (in rough priority order): principles (in rough priority order):
* readability * readability
- scan-ability - scan-ability
@ -19,35 +19,11 @@ following principles (in rough priority order):
* specifics * specifics
- compatibility with version control practices - preserving diffs, - compatibility with version control practices - preserving diffs,
merge-friendliness, etc. merge-friendliness, etc.
- preventing right-ward drift - preventing rightward drift
- minimising vertical space - minimising vertical space
* application * application
- ease of manual application - ease of manual application
- ease of implementation (in Rustfmt, and in other tools/editors/code generators) - ease of implementation (in `rustfmt`, and in other tools/editors/code generators)
- internal consistency - internal consistency
- simplicity of formatting rules - simplicity of formatting rules
## Overarching guidelines
Prefer block indent over visual indent. E.g.,
```rust
// Block indent
a_function_call(
foo,
bar,
);
// Visual indent
a_function_call(foo,
bar);
```
This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
example) and less rightward drift.
Lists should have a trailing comma when followed by a newline, see the block
indent example above. This choice makes moving code (e.g., by copy and paste)
easier and makes smaller diffs.

View file

@ -1,7 +1,9 @@
## Statements
### Let statements ### Let statements
There should be spaces after the `:` and on both sides of the `=` (if they are There should be spaces after the `:` and on both sides of the `=` (if they are
present). No space before the semi-colon. present). No space before the semicolon.
```rust ```rust
// A comment. // A comment.
@ -194,7 +196,7 @@ used to determine whether a let-else statement is *short*.
### Macros in statement position ### Macros in statement position
A macro use in statement position should use parentheses or square brackets as A macro use in statement position should use parentheses or square brackets as
delimiters and should be terminated with a semi-colon. There should be no spaces delimiters and should be terminated with a semicolon. There should be no spaces
between the name, `!`, the delimiters, or the `;`. between the name, `!`, the delimiters, or the `;`.
```rust ```rust
@ -205,13 +207,13 @@ a_macro!(...);
### Expressions in statement position ### Expressions in statement position
There should be no space between the expression and the semi-colon. There should be no space between the expression and the semicolon.
``` ```
<expr>; <expr>;
``` ```
All expressions in statement position should be terminated with a semi-colon, All expressions in statement position should be terminated with a semicolon,
unless they end with a block or are used as the value for a block. unless they end with a block or are used as the value for a block.
E.g., E.g.,
@ -229,7 +231,7 @@ loop {
} }
``` ```
Use a semi-colon where an expression has void type, even if it could be Use a semicolon where an expression has void type, even if it could be
propagated. E.g., propagated. E.g.,
```rust ```rust

View file

@ -347,13 +347,19 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
} }
} else { } else {
let mut br_with_padding = String::with_capacity(6 * indent + 28); let mut br_with_padding = String::with_capacity(6 * indent + 28);
br_with_padding.push_str("\n"); br_with_padding.push('\n');
let padding_amount = let where_indent = 3;
if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() }; let padding_amount = if ending == Ending::Newline {
indent + 4
} else if indent == 0 {
4
} else {
indent + where_indent + "where ".len()
};
for _ in 0..padding_amount { for _ in 0..padding_amount {
br_with_padding.push_str(" "); br_with_padding.push(' ');
} }
let where_preds = where_preds.to_string().replace('\n', &br_with_padding); let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
@ -370,7 +376,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
let where_preds = where_preds.replacen(&br_with_padding, " ", 1); let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
let mut clause = br_with_padding; let mut clause = br_with_padding;
clause.truncate(clause.len() - "where ".len()); // +1 is for `\n`.
clause.truncate(indent + 1 + where_indent);
write!(clause, "<span class=\"where\">where{where_preds}</span>")?; write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
clause clause

View file

@ -860,8 +860,8 @@ fn assoc_method(
w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len()); w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
write!( write!(
w, w,
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a{href} class=\"fn\">{name}</a>\ "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \
{generics}{decl}{notable_traits}{where_clause}", <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
indent = indent_str, indent = indent_str,
vis = vis, vis = vis,
constness = constness, constness = constness,

View file

@ -0,0 +1,2 @@
<h3 class="code-header">impl&lt;D&gt; <a class="struct" href="struct.Delta.html" title="struct foo::Delta">Delta</a>&lt;D&gt;<span class="where fmt-newline">where
D: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></h3>

View file

@ -0,0 +1,3 @@
<code>pub struct Alpha&lt;A&gt;(_)
<span class="where">where
A: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code>

View file

@ -0,0 +1,5 @@
<code>pub trait Bravo&lt;B&gt;<span class="where fmt-newline">where
B: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span>{
// Required method
fn <a href="#tymethod.get" class="fn">get</a>(&amp;self, B: B);
}</code>

View file

@ -0,0 +1,2 @@
<code>pub fn charlie&lt;C&gt;()<span class="where fmt-newline">where
C: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></code>

View file

@ -0,0 +1,2 @@
<code>pub type Golf&lt;T&gt;<span class="where fmt-newline">where
T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span> = <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>;</code>

View file

@ -5,16 +5,20 @@ use std::io::Lines;
pub trait MyTrait { fn dummy(&self) { } } pub trait MyTrait { fn dummy(&self) { } }
// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait" // @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
// @snapshot alpha_trait_decl - '//*[@class="rust item-decl"]/code'
pub struct Alpha<A>(A) where A: MyTrait; pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait" // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
// @snapshot bravo_trait_decl - '//*[@class="rust item-decl"]/code'
pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); } pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait" // @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait"
// @snapshot charlie_fn_decl - '//*[@class="rust item-decl"]/code'
pub fn charlie<C>() where C: MyTrait {} pub fn charlie<C>() where C: MyTrait {}
pub struct Delta<D>(D); pub struct Delta<D>(D);
// @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \ // @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<D> Delta<D>where D: MyTrait" // "impl<D> Delta<D>where D: MyTrait"
// @snapshot SWhere_Echo_impl - '//*[@id="impl-Delta%3CD%3E"]/h3[@class="code-header"]'
impl<D> Delta<D> where D: MyTrait { impl<D> Delta<D> where D: MyTrait {
pub fn delta() {} pub fn delta() {}
} }
@ -65,4 +69,5 @@ impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
// @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \ // @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \
// "type Golf<T>where T: Clone, = (T, T)" // "type Golf<T>where T: Clone, = (T, T)"
// @snapshot golf_type_alias_decl - '//*[@class="rust item-decl"]/code'
pub type Golf<T> where T: Clone = (T, T); pub type Golf<T> where T: Clone = (T, T);

View file

@ -0,0 +1,40 @@
use std::ops::Deref;
use std::rc::Rc;
struct Value<T>(T);
pub trait Wrap<T> {
fn wrap() -> Self;
}
impl<R, A1, A2> Wrap<fn(A1, A2) -> R> for Value<fn(A1, A2) -> R> {
fn wrap() -> Self {
todo!()
}
}
impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> {
fn wrap() -> Self {
todo!()
}
}
impl<F> Deref for Value<Rc<F>> {
type Target = F;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
fn main() {
let var_fn = Value::wrap();
//~^ ERROR type annotations needed for `Value<Rc<_>>`
// The combination of `Value: Wrap` obligation plus the autoderef steps
// (caused by the `Deref` impl above) actually means that the self type
// of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`.
// However, that's only known to us on the error path -- we still need
// to emit an ambiguity error, though.
let _ = var_fn.clone();
}

View file

@ -0,0 +1,17 @@
error[E0282]: type annotations needed for `Value<Rc<_>>`
--> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9
|
LL | let var_fn = Value::wrap();
| ^^^^^^
...
LL | let _ = var_fn.clone();
| ----- type must be known at this point
|
help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified
|
LL | let var_fn: Value<Rc<_>> = Value::wrap();
| ++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View file

@ -9,8 +9,8 @@ LL | let cont: u32 = Generator::create();
| |
help: use a fully-qualified path to a specific available implementation (2 found) help: use a fully-qualified path to a specific available implementation (2 found)
| |
LL | let cont: u32 = <Impl as Generator>::create(); LL | let cont: u32 = </* self type */ as Generator>::create();
| ++++++++ + | +++++++++++++++++++ +
error[E0283]: type annotations needed error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24 --> $DIR/E0283.rs:35:24

View file

@ -65,8 +65,8 @@ LL | MyTrait2::my_fn();
| |
help: use a fully-qualified path to a specific available implementation (2 found) help: use a fully-qualified path to a specific available implementation (2 found)
| |
LL | <Impl1 as MyTrait2>::my_fn(); LL | </* self type */ as MyTrait2>::my_fn();
| +++++++++ + | +++++++++++++++++++ +
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -1,4 +1,4 @@
// Check that imports with nakes super and self don't fail during parsing // Check that imports with naked super and self don't fail during parsing
// FIXME: this shouldn't fail during name resolution either // FIXME: this shouldn't fail during name resolution either
mod a { mod a {