Auto merge of #112661 - matthiaskrgr:rollup-9u5i2zy, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #111212 (Add casting suggestion when assigning negative 2's complement bin or hex literal to a size compatible signed integer)
 - #112304 (Add chapter in rustdoc book for re-exports and add a regression test for `#[doc(hidden)]` behaviour)
 - #112486 (Fix suggestion for E0404 not dealing with multiple generics)
 - #112562 (rustdoc-gui: allow running on Windows)
 - #112621 (Mention `env!` in `option_env!`'s docs)
 - #112634 (add InlineConst check)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-15 16:05:33 +00:00
commit 331249a949
20 changed files with 629 additions and 49 deletions

View File

@ -32,6 +32,10 @@ pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
State::new().bounds_to_string(bounds)
}
pub fn where_bound_predicate_to_string(where_bound_predicate: &ast::WhereBoundPredicate) -> String {
State::new().where_bound_predicate_to_string(where_bound_predicate)
}
pub fn pat_to_string(pat: &ast::Pat) -> String {
State::new().pat_to_string(pat)
}

View File

@ -824,6 +824,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
Self::to_string(|s| s.print_type_bounds(bounds))
}
fn where_bound_predicate_to_string(
&self,
where_bound_predicate: &ast::WhereBoundPredicate,
) -> String {
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
}
fn pat_to_string(&self, pat: &ast::Pat) -> String {
Self::to_string(|s| s.print_pat(pat))
}

View File

@ -623,19 +623,8 @@ impl<'a> State<'a> {
pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
match predicate {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
bound_generic_params,
bounded_ty,
bounds,
..
}) => {
self.print_formal_generic_params(bound_generic_params);
self.print_type(bounded_ty);
self.word(":");
if !bounds.is_empty() {
self.nbsp();
self.print_type_bounds(bounds);
}
ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
self.print_where_bound_predicate(where_bound_predicate);
}
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
lifetime,
@ -658,6 +647,19 @@ impl<'a> State<'a> {
}
}
pub fn print_where_bound_predicate(
&mut self,
where_bound_predicate: &ast::WhereBoundPredicate,
) {
self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
self.print_type(&where_bound_predicate.bounded_ty);
self.word(":");
if !where_bound_predicate.bounds.is_empty() {
self.nbsp();
self.print_type_bounds(&where_bound_predicate.bounds);
}
}
fn print_use_tree(&mut self, tree: &ast::UseTree) {
match &tree.kind {
ast::UseTreeKind::Simple(rename) => {

View File

@ -425,6 +425,7 @@ lint_overflowing_bin_hex = literal out of range for `{$ty}`
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
.positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
.suggestion = consider using the type `{$suggestion_ty}` instead
.sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`
.help = consider using the type `{$suggestion_ty}` instead
lint_overflowing_int = literal out of range for `{$ty}`

View File

@ -1342,6 +1342,8 @@ pub struct OverflowingBinHex<'a> {
pub sign: OverflowingBinHexSign,
#[subdiagnostic]
pub sub: Option<OverflowingBinHexSub<'a>>,
#[subdiagnostic]
pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
}
pub enum OverflowingBinHexSign {
@ -1386,6 +1388,21 @@ pub enum OverflowingBinHexSub<'a> {
Help { suggestion_ty: &'a str },
}
#[derive(Subdiagnostic)]
#[suggestion(
lint_sign_bit_suggestion,
code = "{lit_no_suffix}{uint_ty} as {int_ty}",
applicability = "maybe-incorrect"
)]
pub struct OverflowingBinHexSignBitSub<'a> {
#[primary_span]
pub span: Span,
pub lit_no_suffix: &'a str,
pub negative_val: String,
pub uint_ty: &'a str,
pub int_ty: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(lint_overflowing_int)]
#[note]

View File

@ -3,9 +3,10 @@ use crate::{
lints::{
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
VariantSizeDifferencesDiag,
},
};
use crate::{LateContext, LateLintPass, LintContext};
@ -297,10 +298,50 @@ fn report_bin_hex_error(
}
},
);
let sign_bit_sub = (!negative)
.then(|| {
let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
return None;
};
let Some(bit_width) = int_ty.bit_width() else {
return None; // isize case
};
// Skip if sign bit is not set
if (val & (1 << (bit_width - 1))) == 0 {
return None;
}
let lit_no_suffix =
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
repr_str.split_at(pos).0
} else {
&repr_str
};
Some(OverflowingBinHexSignBitSub {
span: expr.span,
lit_no_suffix,
negative_val: actually.clone(),
int_ty: int_ty.name_str(),
uint_ty: int_ty.to_unsigned().name_str(),
})
})
.flatten();
cx.emit_spanned_lint(
OVERFLOWING_LITERALS,
expr.span,
OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub },
OverflowingBinHex {
ty: t,
lit: repr_str.clone(),
dec: val,
actually,
sign,
sub,
sign_bit_sub,
},
)
}

View File

@ -95,7 +95,10 @@ impl<'tcx> TyCtxt<'tcx> {
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
assert!(matches!(
self.def_kind(ct.def),
DefKind::InlineConst | DefKind::AnonConst
));
let mir_body = self.mir_for_ctfe(ct.def);
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.def.as_local() else { return };

View File

@ -10,7 +10,7 @@ use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@ -1050,7 +1050,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
};
// Confirm that the target is an associated type.
let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
@ -1079,7 +1079,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
return false;
}
if let (
[ast::PathSegment { ident: constrain_ident, args: None, .. }],
[ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
) = (&type_param_path.segments[..], &bounds[..])
{
@ -1087,29 +1087,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&poly_trait_ref.trait_ref.path.segments[..]
{
if ident.span == span {
let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
err.span_suggestion_verbose(
*where_span,
format!("constrain the associated type to `{}`", ident),
format!(
"{}: {}<{} = {}>",
self.r
.tcx
.sess
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
path.segments[..position]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
path.segments[position..]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
ident,
),
where_bound_predicate_to_string(&new_where_bound_predicate),
Applicability::MaybeIncorrect,
);
}
@ -2605,6 +2587,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
fn mk_where_bound_predicate(
path: &Path,
poly_trait_ref: &ast::PolyTraitRef,
ty: &ast::Ty,
) -> Option<ast::WhereBoundPredicate> {
use rustc_span::DUMMY_SP;
let modified_segments = {
let mut segments = path.segments.clone();
let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
let mut segments = ThinVec::from(preceding);
let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
id: DUMMY_NODE_ID,
ident: last.ident,
gen_args: None,
kind: ast::AssocConstraintKind::Equality {
term: ast::Term::Ty(ast::ptr::P(ast::Ty {
kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
id: DUMMY_NODE_ID,
span: DUMMY_SP,
tokens: None,
})),
},
span: DUMMY_SP,
});
match second_last.args.as_deref_mut() {
Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
args.push(added_constraint);
}
Some(_) => return None,
None => {
second_last.args =
Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
args: ThinVec::from([added_constraint]),
span: DUMMY_SP,
})));
}
}
segments.push(second_last.clone());
segments
};
let new_where_bound_predicate = ast::WhereBoundPredicate {
span: DUMMY_SP,
bound_generic_params: ThinVec::new(),
bounded_ty: ast::ptr::P(ty.clone()),
bounds: vec![ast::GenericBound::Trait(
ast::PolyTraitRef {
bound_generic_params: ThinVec::new(),
trait_ref: ast::TraitRef {
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
ref_id: DUMMY_NODE_ID,
},
span: DUMMY_SP,
},
ast::TraitBoundModifier::None,
)],
};
Some(new_where_bound_predicate)
}
/// Report lifetime/lifetime shadowing as an error.
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = struct_span_err!(

View File

@ -250,6 +250,13 @@ changelog-seen = 2
# target when running tests, otherwise this can be omitted.
#nodejs = "node"
# The npm executable to use. Note that this is used for rustdoc-gui tests,
# otherwise this can be omitted.
#
# Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or
# error will be emitted.
#npm = "npm"
# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
#

View File

@ -960,6 +960,8 @@ pub(crate) mod builtin {
///
/// A compile time error is never emitted when using this macro regardless
/// of whether the environment variable is present or not.
/// To emit a compile error if the environment variable is not present,
/// use the [`env!`] macro instead.
///
/// # Examples
///

View File

@ -7,6 +7,7 @@
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](write-documentation/what-to-include.md)
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
- [Re-exports](write-documentation/re-exports.md)
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
- [Documentation tests](write-documentation/documentation-tests.md)
- [Rustdoc-specific lints](lints.md)

View File

@ -0,0 +1,172 @@
# Re-exports
Let's start by explaining what are re-exports. To do so, we will use an example where we are
writing a library (named `lib`) with some types dispatched in sub-modules:
```rust
pub mod sub_module1 {
pub struct Foo;
}
pub mod sub_module2 {
pub struct AnotherFoo;
}
```
Users can import them like this:
```rust,ignore (inline)
use lib::sub_module1::Foo;
use lib::sub_module2::AnotherFoo;
```
But what if you want the types to be available directly at the crate root or if we don't want the
modules to be visible for users? That's where re-exports come in:
```rust,ignore (inline)
// `sub_module1` and `sub_module2` are not visible outside.
mod sub_module1 {
pub struct Foo;
}
mod sub_module2 {
pub struct AnotherFoo;
}
// We re-export both types:
pub use crate::sub_module1::Foo;
pub use crate::sub_module2::AnotherFoo;
```
And now users will be able to do:
```rust,ignore (inline)
use lib::{Foo, AnotherFoo};
```
And since both `sub_module1` and `sub_module2` are private, users won't be able to import them.
Now what's interesting is that the generated documentation for this crate will show both `Foo` and
`AnotherFoo` directly at the crate root, meaning they have been inlined. There are a few rules to
know whether or not a re-exported item will be inlined.
## Inlining rules
If a public item comes from a private module, it will be inlined:
```rust,ignore (inline)
mod private_module {
pub struct Public;
}
pub mod public_mod {
// `Public` will inlined here since `private_module` is private.
pub use super::private_module::Public;
}
// `Public` will not be inlined here since `public_mod` is public.
pub use self::public_mod::Public;
```
Likewise, if an item inherits `#[doc(hidden)]` from any of its ancestors, it will be inlined:
```rust,ignore (inline)
#[doc(hidden)]
pub mod public_mod {
pub struct Public;
}
// `Public` be inlined since its parent (`public_mod`) has `#[doc(hidden)]`.
pub use self::public_mod::Public;
```
If an item has `#[doc(hidden)]`, it won't be inlined (nor visible in the generated documentation):
```rust,ignore (inline)
// This struct won't be visible.
#[doc(hidden)]
pub struct Hidden;
// This re-export won't be visible.
pub use self::Hidden as InlinedHidden;
```
The same applies on re-exports themselves: if you have multiple re-exports and some of them have
`#[doc(hidden)]`, then these ones (and only these) own't appear in the documentation:
```rust,ignore (inline)
mod private_mod {
/// First
pub struct InPrivate;
}
/// Second
#[doc(hidden)]
pub use self::private_mod::InPrivate as Hidden;
/// Third
pub use self::Hidden as Visible;
```
In this case, `InPrivate` will be inlined as `Visible`. However, its documentation will be
`First Third` and not `First Second Third` because the re-export with `Second` as documentation has
`#[doc(hidden)]`, therefore, all its attributes are ignored.
## Inlining with `#[doc(inline)]`
You can use the `#[doc(inline)]` attribute if you want to force an item to be inlined:
```rust,ignore (inline)
pub mod public_mod {
pub struct Public;
}
#[doc(inline)]
pub use self::public_mod::Public;
```
With this code, even though `public_mod::Public` is public and present in the documentation, the
`Public` type will be present both at the crate root and in the `public_mod` module.
## Preventing inlining with `#[doc(no_inline)]`
On the opposite of the `#[doc(inline)]` attribute, if you want to prevent an item from being
inlined, you can use `#[doc(no_inline)]`:
```rust,ignore (inline)
mod private_mod {
pub struct Public;
}
#[doc(no_inline)]
pub use self::private_mod::Public;
```
In the generated documentation, you will see a re-export at the crate root and not the type
directly.
## Attributes
When an item is inlined, its doc comments and most of its attributes will be inlined along with it:
```rust,ignore (inline)
mod private_mod {
/// First
#[cfg(a)]
pub struct InPrivate;
/// Second
#[cfg(b)]
pub use self::InPrivate as Second;
}
/// Third
#[doc(inline)]
#[cfg(c)]
pub use self::private_mod::Second as Visible;
```
In this case, `Visible` will have as documentation `First Second Third` and will also have as `cfg`:
`#[cfg(a, b, c)]`.
[Intra-doc links](./linking-to-items-by-name.md) are resolved relative to where the doc comment is
defined.
There are a few attributes which are not inlined though:
* `#[doc(alias="")]`
* `#[doc(inline)]`
* `#[doc(no_inline)]`
* `#[doc(hidden)]` (because the re-export itself and its attributes are ignored).
All other attributes are inherited when inlined, so that the documentation matches the behavior if
the inlined item was directly defined at the spot where it's shown.

View File

@ -223,12 +223,18 @@ Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will
not eagerly inline it as a module unless you add `#[doc(inline)]`.
If you want to know more about inlining rules, take a look at the
[`re-exports` chapter](./re-exports.md).
### `hidden`
<span id="dochidden"></span>
Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless
the `strip-hidden` pass is removed.
the `strip-hidden` pass is removed. Re-exported items where one of its ancestors has
`#[doc(hidden)]` will be considered the same as private.
You can find more information in the [`re-exports` chapter](./re-exports.md).
### `alias`

View File

@ -14,13 +14,19 @@ fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String>
if global {
command.arg("--global");
}
let lines = command
.output()
.map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
.unwrap_or(String::new());
let lines = match command.output() {
Ok(output) => String::from_utf8_lossy(&output.stdout).into_owned(),
Err(e) => {
eprintln!(
"path to npm can be wrong, provided path: {npm:?}. Try to set npm path \
in config.toml in [build.npm]",
);
panic!("{:?}", e)
}
};
lines
.lines()
.find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
.find_map(|l| l.rsplit(':').next()?.strip_prefix("browser-ui-test@"))
.map(|v| v.to_owned())
}

View File

@ -0,0 +1,143 @@
// Test to enforce rules over re-exports inlining from
// <https://github.com/rust-lang/rust/issues/109449>.
#![crate_name = "foo"]
mod private_module {
#[doc(hidden)]
pub struct Public;
#[doc(hidden)]
pub type Bar = ();
}
#[doc(hidden)]
mod module {
pub struct Public2;
pub type Bar2 = ();
}
#[doc(hidden)]
pub type Bar3 = ();
#[doc(hidden)]
pub struct FooFoo;
// Checking that re-exporting a `#[doc(hidden)]` item will NOT inline it.
pub mod single_reexport {
// @has 'foo/single_reexport/index.html'
// First we check that we have 4 type aliases.
// @count - '//*[@id="main-content"]/*[@class="item-table"]//code' 4
// Then we check that we have the correct link for each re-export.
// @!has - '//*[@href="struct.Foo.html"]' 'Foo'
// @has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
pub use crate::private_module::Public as Foo;
// @!has - '//*[@href="type.Foo2.html"]' 'Foo2'
// @has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;'
pub use crate::private_module::Bar as Foo2;
// @!has - '//*[@href="type.Yo.html"]' 'Yo'
// @has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
pub use crate::Bar3 as Yo;
// @!has - '//*[@href="struct.Yo2.html"]' 'Yo2'
// @has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
pub use crate::FooFoo as Yo2;
// Checking that each file is also created as expected.
// @!has 'foo/single_reexport/struct.Foo.html'
// @!has 'foo/single_reexport/type.Foo2.html'
// @!has 'foo/single_reexport/type.Yo.html'
// @!has 'foo/single_reexport/struct.Yo2.html'
}
// However, re-exporting an item inheriting `#[doc(hidden)]` will inline it.
pub mod single_reexport_inherit_hidden {
// @has 'foo/single_reexport_inherit_hidden/index.html'
// @has - '//*[@href="struct.Foo3.html"]' 'Foo3'
pub use crate::module::Public2 as Foo3;
// @has - '//*[@href="type.Foo4.html"]' 'Foo4'
pub use crate::module::Bar2 as Foo4;
// @has 'foo/single_reexport_inherit_hidden/struct.Foo3.html'
// @has 'foo/single_reexport_inherit_hidden/type.Foo4.html'
}
pub mod single_reexport_no_inline {
// First we ensure that we only have re-exports and no inlined items.
// @has 'foo/single_reexport_no_inline/index.html'
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports'
// Now we check that we don't have links to the items, just `pub use`.
// @has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;'
// @!has - '//*[@id="main-content"]//a' 'XFoo'
#[doc(no_inline)]
pub use crate::private_module::Public as XFoo;
// @has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;'
// @!has - '//*[@id="main-content"]//a' 'Foo2'
#[doc(no_inline)]
pub use crate::private_module::Bar as Foo2;
// @has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;'
// @!has - '//*[@id="main-content"]//a' 'Yo'
#[doc(no_inline)]
pub use crate::Bar3 as Yo;
// @has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;'
// @!has - '//*[@id="main-content"]//a' 'Yo2'
#[doc(no_inline)]
pub use crate::FooFoo as Yo2;
// @has - '//*[@id="main-content"]//*' 'pub use crate::module::Public2 as Foo3;'
// @!has - '//*[@id="main-content"]//a' 'Foo3'
#[doc(no_inline)]
pub use crate::module::Public2 as Foo3;
// @has - '//*[@id="main-content"]//*' 'pub use crate::module::Bar2 as Foo4;'
// @!has - '//*[@id="main-content"]//a' 'Foo4'
#[doc(no_inline)]
pub use crate::module::Bar2 as Foo4;
}
// Checking that glob re-exports don't inline `#[doc(hidden)]` items.
pub mod glob_reexport {
// With glob re-exports, we don't inline `#[doc(hidden)]` items so only `module` items
// should be inlined.
// @has 'foo/glob_reexport/index.html'
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports'
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions'
// Now we check we have 1 re-export and 2 inlined items.
// If not item from a glob re-export is visible, we don't show the re-export.
// @!has - '//*[@id="main-content"]//*' 'pub use crate::private_module::*;'
pub use crate::private_module::*;
// @has - '//*[@id="main-content"]//*' 'pub use crate::*;'
pub use crate::*;
// This one should be inlined.
// @!has - '//*[@id="main-content"]//*' 'pub use crate::module::*;'
// @has - '//*[@id="main-content"]//a[@href="struct.Public2.html"]' 'Public2'
// @has - '//*[@id="main-content"]//a[@href="type.Bar2.html"]' 'Bar2'
// And we check that the two files were created too.
// @has 'foo/glob_reexport/struct.Public2.html'
// @has 'foo/glob_reexport/type.Bar2.html'
pub use crate::module::*;
}
mod private {
/// Original.
pub struct Bar3;
}
// Checking that `#[doc(hidden)]` re-exports documentation isn't generated.
pub mod doc_hidden_reexport {
// @has 'foo/doc_hidden_reexport/index.html'
// Ensure there is only one item in this page and that it's a struct.
// @count - '//*[@class="item-name"]' 1
// @has - '//a[@class="struct"]' 'Reexport'
// Check that the `#[doc(hidden)]` re-export's attributes are not taken into account.
// @has - '//*[@class="desc docblock-short"]' 'Visible. Original.'
/// Hidden.
#[doc(hidden)]
pub use crate::private::Bar3;
/// Visible.
pub use self::Bar3 as Reexport;
}

View File

@ -16,17 +16,33 @@ warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:10:16
|
LL | let fail = 0b1000_0001i8;
| ^^^^^^^^^^^^^ help: consider using the type `u8` instead: `0b1000_0001u8`
| ^^^^^^^^^^^^^
|
= note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8`
help: consider using the type `u8` instead
|
LL | let fail = 0b1000_0001u8;
| ~~~~~~~~~~~~~
help: to use as a negative number (decimal `-127`), consider using the type `u8` for the literal and cast it to `i8`
|
LL | let fail = 0b1000_0001u8 as i8;
| ~~~~~~~~~~~~~~~~~~~
warning: literal out of range for `i64`
--> $DIR/type-overflow.rs:12:16
|
LL | let fail = 0x8000_0000_0000_0000i64;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x8000_0000_0000_0000u64`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64`
help: consider using the type `u64` instead
|
LL | let fail = 0x8000_0000_0000_0000u64;
| ~~~~~~~~~~~~~~~~~~~~~~~~
help: to use as a negative number (decimal `-9223372036854775808`), consider using the type `u64` for the literal and cast it to `i64`
|
LL | let fail = 0x8000_0000_0000_0000u64 as i64;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
warning: literal out of range for `u32`
--> $DIR/type-overflow.rs:14:16
@ -44,6 +60,10 @@ LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
|
= note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128`
= help: consider using the type `u128` instead
help: to use as a negative number (decimal `-170141183460469231731687303715884105728`), consider using the type `u128` for the literal and cast it to `i128`
|
LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
warning: literal out of range for `i32`
--> $DIR/type-overflow.rs:19:16
@ -53,6 +73,10 @@ LL | let fail = 0x8FFF_FFFF_FFFF_FFFE;
|
= note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
= help: consider using the type `i128` instead
help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32`
|
LL | let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:21:17

View File

@ -0,0 +1,11 @@
// run-pass
#![feature(inline_const_pat)]
#![allow(dead_code)]
#![allow(incomplete_features)]
fn foo<const V: usize>() {
match 0 {
const { 1 << 5 } | _ => {}
}
}
fn main() {}

View File

@ -0,0 +1,31 @@
// run-rustfix
use std::fmt::Debug;
use std::marker::PhantomData;
use std::convert::{self, TryFrom};
#[allow(unused)]
struct Codec<EncodeLine, DecodeLine> {
phantom_decode: PhantomData<DecodeLine>,
phantom_encode: PhantomData<EncodeLine>,
}
pub enum ParseError {}
impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
DecodeLine: Debug + convert::TryFrom<String>,
DecodeLine: convert::TryFrom<String, Error = ParseError>,
//~^ ERROR expected trait, found enum `ParseError`
//~| HELP constrain the associated type to `ParseError`
{
}
impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
DecodeLine: Debug + TryFrom<String>,
DecodeLine: TryFrom<String, Error = ParseError>,
//~^ ERROR expected trait, found enum `ParseError`
//~| HELP constrain the associated type to `ParseError`
{
}
fn main() {}

View File

@ -0,0 +1,31 @@
// run-rustfix
use std::fmt::Debug;
use std::marker::PhantomData;
use std::convert::{self, TryFrom};
#[allow(unused)]
struct Codec<EncodeLine, DecodeLine> {
phantom_decode: PhantomData<DecodeLine>,
phantom_encode: PhantomData<EncodeLine>,
}
pub enum ParseError {}
impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
DecodeLine: Debug + convert::TryFrom<String>,
<DecodeLine as convert::TryFrom<String>>::Error: ParseError,
//~^ ERROR expected trait, found enum `ParseError`
//~| HELP constrain the associated type to `ParseError`
{
}
impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
DecodeLine: Debug + TryFrom<String>,
<DecodeLine as TryFrom<String>>::Error: ParseError,
//~^ ERROR expected trait, found enum `ParseError`
//~| HELP constrain the associated type to `ParseError`
{
}
fn main() {}

View File

@ -0,0 +1,25 @@
error[E0404]: expected trait, found enum `ParseError`
--> $DIR/issue-112472-multi-generics-suggestion.rs:17:54
|
LL | <DecodeLine as convert::TryFrom<String>>::Error: ParseError,
| ^^^^^^^^^^ not a trait
|
help: constrain the associated type to `ParseError`
|
LL | DecodeLine: convert::TryFrom<String, Error = ParseError>,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0404]: expected trait, found enum `ParseError`
--> $DIR/issue-112472-multi-generics-suggestion.rs:25:45
|
LL | <DecodeLine as TryFrom<String>>::Error: ParseError,
| ^^^^^^^^^^ not a trait
|
help: constrain the associated type to `ParseError`
|
LL | DecodeLine: TryFrom<String, Error = ParseError>,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0404`.