mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
commit
54d6738a8d
@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_from_span: Span,
|
||||
move_from_desc: &str,
|
||||
) -> 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
|
||||
|
@ -12,6 +12,7 @@ use rustc_hir::def::DefKind;
|
||||
use rustc_hir_analysis::autoderef::{self, Autoderef};
|
||||
use rustc_infer::infer::canonical::OriginalQueryValues;
|
||||
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
||||
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::middle::stability;
|
||||
@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Encountered a real ambiguity, so abort the lookup. If `ty` is not
|
||||
// an `Err`, report the right "type annotations needed" error pointing
|
||||
// to it.
|
||||
// Ended up encountering a type variable when doing autoderef,
|
||||
// but it may not be a type variable after processing obligations
|
||||
// in our local `FnCtxt`, so don't call `structurally_resolved_type`.
|
||||
let ty = &bad_ty.ty;
|
||||
let ty = self
|
||||
.probe_instantiate_query_response(span, &orig_values, ty)
|
||||
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
|
||||
let ty = self.structurally_resolved_type(span, ty.value);
|
||||
assert!(matches!(ty.kind(), ty::Error(_)));
|
||||
let ty = self.resolve_vars_if_possible(ty.value);
|
||||
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 {
|
||||
static_candidates: Vec::new(),
|
||||
unsatisfied_predicates: Vec::new(),
|
||||
|
@ -54,7 +54,7 @@ fn path_to_string(path: &syn::Path) -> String {
|
||||
|
||||
/// Returns an error diagnostic on span `span` with msg `msg`.
|
||||
#[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)
|
||||
}
|
||||
|
||||
@ -77,11 +77,9 @@ pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic {
|
||||
let span = attr.span().unwrap();
|
||||
let path = path_to_string(attr.path());
|
||||
match attr.meta {
|
||||
Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
|
||||
Meta::NameValue(_) => {
|
||||
span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
|
||||
}
|
||||
Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")),
|
||||
Meta::Path(_) => span_err(span, format!("`#[{path}]` is not a valid attribute")),
|
||||
Meta::NameValue(_) => span_err(span, format!("`#[{path} = ...]` is not a valid attribute")),
|
||||
Meta::List(_) => span_err(span, format!("`#[{path}(...)]` is not a valid attribute")),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
|
||||
throw_span_err!(
|
||||
attr.span().unwrap(),
|
||||
&format!(
|
||||
format!(
|
||||
"diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
|
||||
)
|
||||
);
|
||||
|
@ -347,7 +347,7 @@ pub(crate) trait HasFieldMap {
|
||||
None => {
|
||||
span_err(
|
||||
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();
|
||||
quote! {
|
||||
|
@ -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 non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
|
||||
let message = if non_blanket_impl_count == 1 {
|
||||
"use the fully-qualified path to the only available implementation".to_string()
|
||||
} else {
|
||||
// If there is only one implementation of the trait, suggest using it.
|
||||
// Otherwise, use a placeholder comment for the implementation.
|
||||
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!(
|
||||
"use a fully-qualified path to a specific available implementation ({} found)",
|
||||
non_blanket_impl_count
|
||||
)
|
||||
};
|
||||
),
|
||||
"</* self type */ as ".to_string()
|
||||
)};
|
||||
let mut suggestions = vec![(
|
||||
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 {
|
||||
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
|
||||
|
@ -32,7 +32,8 @@ use crate::ptr;
|
||||
/// * The memory referenced by the returned slice must not be mutated for the duration
|
||||
/// 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`].
|
||||
///
|
||||
/// # 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`.
|
||||
/// 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`].
|
||||
///
|
||||
/// [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 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!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// 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
|
||||
/// 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`].
|
||||
///
|
||||
/// 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 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!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// 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
|
||||
/// (not derived from the return value) for the duration of lifetime `'a`.
|
||||
/// 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`].
|
||||
///
|
||||
/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements.
|
||||
|
@ -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.
|
||||
|
||||
Thus, there are productivity benefits to using a formatting tool (such as
|
||||
rustfmt), and even larger benefits by using a community-consistent formatting,
|
||||
typically by using a formatting tool's default settings.
|
||||
`rustfmt`), and even larger benefits by using a community-consistent
|
||||
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
|
||||
|
||||
@ -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
|
||||
outside of string literals and comments must be a multiple of four).
|
||||
* 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
|
||||
|
||||
@ -48,11 +99,7 @@ fn bar() {}
|
||||
fn baz() {}
|
||||
```
|
||||
|
||||
Formatting tools should make the bounds on blank lines configurable: there
|
||||
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.
|
||||
|
||||
Formatting tools may wish to make the bounds on blank lines configurable.
|
||||
|
||||
### [Module-level items](items.md)
|
||||
### [Statements](statements.md)
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
[Introduction](README.md)
|
||||
|
||||
- [Module-level items](items.md)
|
||||
- [Items](items.md)
|
||||
- [Statements](statements.md)
|
||||
- [Expressions](expressions.md)
|
||||
- [Types](types.md)
|
||||
- [Non-formatting conventions](advice.md)
|
||||
- [Types and Bounds](types.md)
|
||||
- [Other style advice](advice.md)
|
||||
- [`Cargo.toml` conventions](cargo.md)
|
||||
- [Principles used for deciding these guidelines](principles.md)
|
||||
- [Guiding principles and rationale](principles.md)
|
||||
|
@ -25,9 +25,9 @@ if y {
|
||||
* Local variables shall be `snake_case`,
|
||||
* Macro names shall be `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
|
||||
trailing underscore to make the name legal (e.g., `crate_`), or use raw
|
||||
identifiers if possible.
|
||||
* When a name is forbidden because it is a reserved word (such as `crate`),
|
||||
either use a raw identifier (`r#crate`) or use a trailing underscore
|
||||
(`crate_`). Don't misspell the word (`krate`).
|
||||
|
||||
### Modules
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Cargo.toml conventions
|
||||
# `Cargo.toml` 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
|
||||
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
|
||||
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
|
||||
bracket at the start of a line by itself after the last item.
|
||||
|
||||
```rust
|
||||
authors = [
|
||||
"A Uthor <a.uthor@example.org>",
|
||||
"Another Author <author@example.net>",
|
||||
some_feature = [
|
||||
"another_feature",
|
||||
"yet_another_feature",
|
||||
"some_dependency?/some_feature",
|
||||
]
|
||||
```
|
||||
|
||||
@ -54,11 +55,11 @@ version = "4.5.6"
|
||||
|
||||
## Metadata conventions
|
||||
|
||||
The authors list should consist of strings that each contain an author name
|
||||
followed by an email address in angle brackets: `Full Name <email@address>`.
|
||||
It should not contain bare email addresses, or names without email addresses.
|
||||
(The authors list may also include a mailing list address without an associated
|
||||
name.)
|
||||
The authors list, if present, should consist of strings that each contain an
|
||||
author name followed by an email address in angle brackets: `Full Name
|
||||
<email@address>`. It should not contain bare email addresses, or names without
|
||||
email addresses. (The authors list may also include a mailing list address
|
||||
without an associated name.)
|
||||
|
||||
The license field must contain a valid [SPDX
|
||||
expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),
|
||||
|
@ -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.
|
||||
|
||||
```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 {
|
||||
...
|
||||
},
|
||||
|
@ -1,5 +1,10 @@
|
||||
## 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
|
||||
alphabetically.
|
||||
|
||||
@ -15,8 +20,8 @@ Tools should make the above ordering optional.
|
||||
|
||||
### Function definitions
|
||||
|
||||
In Rust, one finds functions by searching for `fn [function-name]`; It's
|
||||
important that you style your code so that it's very searchable in this way.
|
||||
In Rust, people often find functions by searching for `fn [function-name]`, so
|
||||
the formatting of function definitions shold enable this.
|
||||
|
||||
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.
|
||||
|
||||
Format each variant accordingly as either a struct, tuple struct, or identifier,
|
||||
which doesn't require special formatting (but without the `struct` keyword.
|
||||
Format each variant accordingly as either a struct (but without the `struct`
|
||||
keyword), a tuple struct, or an identifier (which doesn't require special
|
||||
formatting):
|
||||
|
||||
```rust
|
||||
enum FooBar {
|
||||
@ -139,7 +145,7 @@ union Foo {
|
||||
|
||||
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
|
||||
parentheses or semi-colon:
|
||||
parentheses or semicolon:
|
||||
|
||||
```rust
|
||||
pub struct Foo(String, u8);
|
||||
@ -230,7 +236,7 @@ impl Bar
|
||||
|
||||
`extern crate foo;`
|
||||
|
||||
Use spaces around keywords, no spaces around the semi-colon.
|
||||
Use spaces around keywords, no spaces around the semicolon.
|
||||
|
||||
|
||||
### Modules
|
||||
@ -245,7 +251,7 @@ mod foo;
|
||||
```
|
||||
|
||||
Use spaces around keywords and before the opening brace, no spaces around the
|
||||
semi-colon.
|
||||
semicolon.
|
||||
|
||||
### macro\_rules!
|
||||
|
||||
@ -478,8 +484,8 @@ foo::{
|
||||
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.
|
||||
|
||||
Within a group of imports, imports must be sorted ascii-betically. Groups of
|
||||
imports must not be merged or re-ordered.
|
||||
Within a group of imports, imports must be sorted ASCIIbetically (uppercase
|
||||
before lowercase). Groups of imports must not be merged or re-ordered.
|
||||
|
||||
|
||||
E.g., input:
|
||||
@ -505,13 +511,9 @@ use b;
|
||||
Because of `macro_use`, attributes must also start a new group and prevent
|
||||
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
|
||||
|
||||
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
|
||||
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}};`.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Guiding principles and rationale
|
||||
|
||||
When deciding on style guidelines, the style team tried to be guided by the
|
||||
following principles (in rough priority order):
|
||||
When deciding on style guidelines, the style team follows these guiding
|
||||
principles (in rough priority order):
|
||||
|
||||
* readability
|
||||
- scan-ability
|
||||
@ -19,35 +19,11 @@ following principles (in rough priority order):
|
||||
* specifics
|
||||
- compatibility with version control practices - preserving diffs,
|
||||
merge-friendliness, etc.
|
||||
- preventing right-ward drift
|
||||
- preventing rightward drift
|
||||
- minimising vertical space
|
||||
|
||||
* 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
|
||||
- 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.
|
||||
|
@ -1,7 +1,9 @@
|
||||
## Statements
|
||||
|
||||
### Let statements
|
||||
|
||||
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
|
||||
// A comment.
|
||||
@ -194,7 +196,7 @@ used to determine whether a let-else statement is *short*.
|
||||
### Macros in statement position
|
||||
|
||||
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 `;`.
|
||||
|
||||
```rust
|
||||
@ -205,13 +207,13 @@ a_macro!(...);
|
||||
|
||||
### 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>;
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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.,
|
||||
|
||||
```rust
|
||||
|
@ -347,13 +347,19 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
}
|
||||
} else {
|
||||
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 =
|
||||
if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() };
|
||||
let where_indent = 3;
|
||||
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 {
|
||||
br_with_padding.push_str(" ");
|
||||
br_with_padding.push(' ');
|
||||
}
|
||||
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 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>")?;
|
||||
clause
|
||||
|
@ -860,8 +860,8 @@ fn assoc_method(
|
||||
w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
|
||||
write!(
|
||||
w,
|
||||
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a{href} class=\"fn\">{name}</a>\
|
||||
{generics}{decl}{notable_traits}{where_clause}",
|
||||
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \
|
||||
<a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
|
||||
indent = indent_str,
|
||||
vis = vis,
|
||||
constness = constness,
|
||||
|
2
tests/rustdoc/where.SWhere_Echo_impl.html
Normal file
2
tests/rustdoc/where.SWhere_Echo_impl.html
Normal file
@ -0,0 +1,2 @@
|
||||
<h3 class="code-header">impl<D> <a class="struct" href="struct.Delta.html" title="struct foo::Delta">Delta</a><D><span class="where fmt-newline">where
|
||||
D: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></h3>
|
@ -1,3 +1,3 @@
|
||||
<pre class="rust item-decl"><code>pub struct Simd<T>(_)
|
||||
<span class="where">where
|
||||
T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
|
||||
T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre>
|
||||
|
3
tests/rustdoc/where.alpha_trait_decl.html
Normal file
3
tests/rustdoc/where.alpha_trait_decl.html
Normal file
@ -0,0 +1,3 @@
|
||||
<code>pub struct Alpha<A>(_)
|
||||
<span class="where">where
|
||||
A: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code>
|
5
tests/rustdoc/where.bravo_trait_decl.html
Normal file
5
tests/rustdoc/where.bravo_trait_decl.html
Normal file
@ -0,0 +1,5 @@
|
||||
<code>pub trait Bravo<B><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>(&self, B: B);
|
||||
}</code>
|
2
tests/rustdoc/where.charlie_fn_decl.html
Normal file
2
tests/rustdoc/where.charlie_fn_decl.html
Normal file
@ -0,0 +1,2 @@
|
||||
<code>pub fn charlie<C>()<span class="where fmt-newline">where
|
||||
C: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></code>
|
2
tests/rustdoc/where.golf_type_alias_decl.html
Normal file
2
tests/rustdoc/where.golf_type_alias_decl.html
Normal file
@ -0,0 +1,2 @@
|
||||
<code>pub type Golf<T><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>
|
@ -5,16 +5,20 @@ use std::io::Lines;
|
||||
pub trait MyTrait { fn dummy(&self) { } }
|
||||
|
||||
// @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;
|
||||
// @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); }
|
||||
// @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 struct Delta<D>(D);
|
||||
|
||||
// @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \
|
||||
// "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 {
|
||||
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"]' \
|
||||
// "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);
|
||||
|
@ -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();
|
||||
}
|
@ -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`.
|
@ -9,8 +9,8 @@ LL | let cont: u32 = Generator::create();
|
||||
|
|
||||
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
|
||||
--> $DIR/E0283.rs:35:24
|
||||
|
@ -65,8 +65,8 @@ LL | MyTrait2::my_fn();
|
||||
|
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
mod a {
|
||||
|
Loading…
Reference in New Issue
Block a user