Make Flex only overflow on epsilon (#31890)

diff --git a/packages/flutter/lib/src/foundation/constants.dart b/packages/flutter/lib/src/foundation/constants.dart
index fc56a0c..804ece0 100644
--- a/packages/flutter/lib/src/foundation/constants.dart
+++ b/packages/flutter/lib/src/foundation/constants.dart
@@ -31,3 +31,10 @@
 /// a particular block of code will not be executed in debug mode, and hence
 /// can be removed.
 const bool kDebugMode = !kReleaseMode && !kProfileMode;
+
+/// The epsilon of tolerable double precision error.
+///
+/// This is used in various places in the framework to allow for floating point
+/// precision loss in calculations. Differences below this threshold are safe to
+/// disregard.
+const double precisionErrorTolerance = 1e-10;
diff --git a/packages/flutter/lib/src/rendering/flex.dart b/packages/flutter/lib/src/rendering/flex.dart
index d034da8..5504339 100644
--- a/packages/flutter/lib/src/rendering/flex.dart
+++ b/packages/flutter/lib/src/rendering/flex.dart
@@ -470,6 +470,9 @@
 
   // Set during layout if overflow occurred on the main axis.
   double _overflow;
+  // Check whether any meaningful overflow is present. Values below an epsilon
+  // are treated as not overflowing.
+  bool get _hasOverflow => _overflow > precisionErrorTolerance;
 
   @override
   void setupParentData(RenderBox child) {
@@ -849,7 +852,6 @@
     }
     actualSizeDelta = actualSize - allocatedSize;
     _overflow = math.max(0.0, -actualSizeDelta);
-
     final double remainingSpace = math.max(0.0, actualSizeDelta);
     double leadingSpace;
     double betweenSpace;
@@ -941,7 +943,7 @@
 
   @override
   void paint(PaintingContext context, Offset offset) {
-    if (_overflow <= 0.0) {
+    if (!_hasOverflow) {
       defaultPaint(context, offset);
       return;
     }
@@ -997,12 +999,12 @@
   }
 
   @override
-  Rect describeApproximatePaintClip(RenderObject child) => _overflow > 0.0 ? Offset.zero & size : null;
+  Rect describeApproximatePaintClip(RenderObject child) => _hasOverflow ? Offset.zero & size : null;
 
   @override
   String toStringShort() {
     String header = super.toStringShort();
-    if (_overflow is double && _overflow > 0.0)
+    if (_overflow is double && _hasOverflow)
       header += ' OVERFLOWING';
     return header;
   }
diff --git a/packages/flutter/lib/src/rendering/sliver.dart b/packages/flutter/lib/src/rendering/sliver.dart
index 5169cc5..8e613f8 100644
--- a/packages/flutter/lib/src/rendering/sliver.dart
+++ b/packages/flutter/lib/src/rendering/sliver.dart
@@ -690,9 +690,6 @@
   ///  * [RenderViewport.cacheExtent] for a description of a viewport's cache area.
   final double cacheExtent;
 
-  /// The epsilon of tolerable double precision error.
-  static const double precisionErrorTolerance = 1e-10;
-
   /// Asserts that this geometry is internally consistent.
   ///
   /// Does nothing if asserts are disabled. Always returns true.
diff --git a/packages/flutter/lib/src/rendering/sliver_list.dart b/packages/flutter/lib/src/rendering/sliver_list.dart
index 6baf760..5fa8897 100644
--- a/packages/flutter/lib/src/rendering/sliver_list.dart
+++ b/packages/flutter/lib/src/rendering/sliver_list.dart
@@ -120,7 +120,7 @@
 
       final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild);
       // firstChildScrollOffset may contain double precision error
-      if (firstChildScrollOffset < -SliverGeometry.precisionErrorTolerance) {
+      if (firstChildScrollOffset < -precisionErrorTolerance) {
         // The first child doesn't fit within the viewport (underflow) and
         // there may be additional children above it. Find the real first child
         // and then correct the scroll position so that there's room for all and
diff --git a/packages/flutter/test/rendering/flex_test.dart b/packages/flutter/test/rendering/flex_test.dart
index 852c64f..a4fc043 100644
--- a/packages/flutter/test/rendering/flex_test.dart
+++ b/packages/flutter/test/rendering/flex_test.dart
@@ -20,6 +20,38 @@
     expect(flex.size.height, equals(200.0), reason: 'flex height');
   });
 
+  test('Inconsequential overflow is ignored', () {
+    // These values are meant to simulate slight rounding errors in addition
+    // or subtraction in the layout code for Flex.
+    const double slightlyLarger = 438.8571428571429;
+    const double slightlySmaller = 438.85714285714283;
+    final List<dynamic> exceptions = <dynamic>[];
+    final FlutterExceptionHandler oldHandler = FlutterError.onError;
+    FlutterError.onError = (FlutterErrorDetails details) {
+      exceptions.add(details.exception);
+    };
+    const BoxConstraints square = BoxConstraints.tightFor(width: slightlyLarger, height: 100.0);
+    final RenderConstrainedBox box1 = RenderConstrainedBox(additionalConstraints: square);
+    final RenderFlex flex = RenderFlex(
+      textDirection: TextDirection.ltr,
+      mainAxisSize: MainAxisSize.min,
+    );
+    final RenderConstrainedOverflowBox parent = RenderConstrainedOverflowBox(
+      minWidth: 0.0,
+      maxWidth: slightlySmaller,
+      minHeight: 0.0,
+      maxHeight: 400.0,
+      child: flex,
+    );
+    flex.add(box1);
+    layout(parent);
+    expect(flex.size, const Size(slightlySmaller, 100.0));
+    pumpFrame(phase: EnginePhase.paint);
+
+    expect(exceptions, isEmpty);
+    FlutterError.onError = oldHandler;
+  });
+
   test('Vertical Overflow', () {
     final RenderConstrainedBox flexible = RenderConstrainedBox(
       additionalConstraints: const BoxConstraints.expand()
diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart
index 3a1482f..f0809d3 100644
--- a/packages/flutter_test/lib/src/matchers.dart
+++ b/packages/flutter_test/lib/src/matchers.dart
@@ -207,10 +207,11 @@
 /// Asserts that two [double]s are equal, within some tolerated error.
 ///
 /// Two values are considered equal if the difference between them is within
-/// 1e-10 of the larger one. This is an arbitrary value which can be adjusted
-/// using the `epsilon` argument. This matcher is intended to compare floating
-/// point numbers that are the result of different sequences of operations, such
-/// that they may have accumulated slightly different errors.
+/// [precisionErrorTolerance] of the larger one. This is an arbitrary value
+/// which can be adjusted using the `epsilon` argument. This matcher is intended
+/// to compare floating point numbers that are the result of different sequences
+/// of operations, such that they may have accumulated slightly different
+/// errors.
 ///
 /// See also:
 ///
@@ -218,24 +219,25 @@
 ///    required and not named.
 ///  * [inInclusiveRange], which matches if the argument is in a specified
 ///    range.
-Matcher moreOrLessEquals(double value, { double epsilon = 1e-10 }) {
+Matcher moreOrLessEquals(double value, { double epsilon = precisionErrorTolerance }) {
   return _MoreOrLessEquals(value, epsilon);
 }
 
 /// Asserts that two [Rect]s are equal, within some tolerated error.
 ///
 /// Two values are considered equal if the difference between them is within
-/// 1e-10 of the larger one. This is an arbitrary value which can be adjusted
-/// using the `epsilon` argument. This matcher is intended to compare floating
-/// point numbers that are the result of different sequences of operations, such
-/// that they may have accumulated slightly different errors.
+/// [precisionErrorTolerance] of the larger one. This is an arbitrary value
+/// which can be adjusted using the `epsilon` argument. This matcher is intended
+/// to compare floating point numbers that are the result of different sequences
+/// of operations, such that they may have accumulated slightly different
+/// errors.
 ///
 /// See also:
 ///
 ///  * [moreOrLessEquals], which is for [double]s.
 ///  * [within], which offers a generic version of this functionality that can
 ///    be used to match [Rect]s as well as other types.
-Matcher rectMoreOrLessEquals(Rect value, { double epsilon = 1e-10 }) {
+Matcher rectMoreOrLessEquals(Rect value, { double epsilon = precisionErrorTolerance }) {
   return _IsWithinDistance<Rect>(_rectDistance, value, epsilon);
 }